Friday, May 3, 2013

UI elements lost after Activity/Fragment re-created

Last two post "Understand lifecycle of Activity and Fragment" and "Different case in lifecycle of Activity and Fragment", we have introduction about lifecycle. Now we check how it affect on real case.

In the layout of our fragment, we have 4 ImageView.
  • image_a: With android:src defined in XML.
  • image_b: Load image in onCreateView().
  • image_c: Load image in onCreateView(), only if savedInstanceState == null.
  • image_d: Load image in runtime, triggered by button clicked
In case image_c and image_d, the image will lost when orientation changed, or "Don't keep activities".




Code List -

Modify our custom FragmentActivity (MyFragmentActivity.java) and Fragment (MyFragment.java.java) to display savedInstanceState also.

MyFragmentActivity.java
package com.example.androidfragmenttest;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.widget.Toast;

public class MyFragmentActivity extends FragmentActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
recLifeCycle_with_savedInstanceState(savedInstanceState);
super.onCreate(savedInstanceState);
}

@Override
protected void onStart() {
recLifeCycle();
super.onStart();
}

@Override
protected void onRestart() {
recLifeCycle();
super.onRestart();
}

@Override
protected void onResume() {
recLifeCycle();
super.onResume();
}

@Override
protected void onPause() {
recLifeCycle();
super.onPause();
}

@Override
protected void onStop() {
recLifeCycle();
super.onStop();
}

@Override
protected void onDestroy() {
recLifeCycle();
super.onDestroy();
}

public void recLifeCycle(){

String className = getClass().getSimpleName();
StackTraceElement[] s = Thread.currentThread().getStackTrace();
String methodName = s[3].getMethodName();

Toast.makeText(getApplicationContext(),
className + "." + methodName, Toast.LENGTH_SHORT).show();
Log.i("MYTAG", className + "." + methodName);

}

public void recLifeCycle(String note){
String className = getClass().getSimpleName();
StackTraceElement[] s = Thread.currentThread().getStackTrace();
String methodName = s[3].getMethodName();

Toast.makeText(getApplicationContext(),
className + "." + methodName, Toast.LENGTH_SHORT).show();
Log.i("MYTAG", className + "." + methodName + " / " + note);
}

public void recLifeCycle_with_savedInstanceState(Bundle state){

String stateMsg;
if(state == null){
stateMsg = "savedInstanceState == null";
}else{
stateMsg = "savedInstanceState != null";
}

String className = getClass().getSimpleName();
StackTraceElement[] s = Thread.currentThread().getStackTrace();
String methodName = s[3].getMethodName();

Toast.makeText(getApplicationContext(),
className + "." + methodName, Toast.LENGTH_SHORT).show();
Log.i("MYTAG", className + "." + methodName + " / " + stateMsg);
}

}


MyFragment.java
package com.example.androidfragmenttest;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

public class MyFragment extends Fragment {

@Override
public void onAttach(Activity activity) {
recLifeCycle();
super.onAttach(activity);
}

@Override
public void onCreate(Bundle savedInstanceState) {
recLifeCycle_with_savedInstanceState(savedInstanceState);
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

recLifeCycle_with_savedInstanceState(savedInstanceState);
return super.onCreateView(inflater, container, savedInstanceState);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
recLifeCycle_with_savedInstanceState(savedInstanceState);
super.onActivityCreated(savedInstanceState);
}

@Override
public void onStart() {
recLifeCycle();
super.onStart();
}

@Override
public void onResume() {
recLifeCycle();
super.onResume();
}

@Override
public void onPause() {
recLifeCycle();
super.onPause();
}

@Override
public void onStop() {
recLifeCycle();
super.onStop();
}

@Override
public void onDestroyView() {
recLifeCycle();
super.onDestroyView();
}

@Override
public void onDestroy() {
recLifeCycle();
super.onDestroy();
}

@Override
public void onDetach() {
recLifeCycle();
super.onDetach();
}

public void recLifeCycle(){

String className = getClass().getSimpleName();
StackTraceElement[] s = Thread.currentThread().getStackTrace();
String methodName = s[3].getMethodName();

String msg = className + "." + methodName;

Toast.makeText(getActivity(),
msg, Toast.LENGTH_SHORT).show();
Log.i("MYTAG", msg);
}

public void recLifeCycle(String note){

String className = getClass().getSimpleName();
StackTraceElement[] s = Thread.currentThread().getStackTrace();
String methodName = s[3].getMethodName();

String msg = className + "." + methodName;

Toast.makeText(getActivity(),
msg, Toast.LENGTH_SHORT).show();
Log.i("MYTAG", msg + " / " + note);
}

public void recLifeCycle_with_savedInstanceState(Bundle state){

String stateMsg;
if(state == null){
stateMsg = "savedInstanceState == null";
}else{
stateMsg = "savedInstanceState != null";
}

String className = getClass().getSimpleName();
StackTraceElement[] s = Thread.currentThread().getStackTrace();
String methodName = s[3].getMethodName();

String msg = className + "." + methodName + " / " + stateMsg;

Toast.makeText(getActivity(),
msg, Toast.LENGTH_SHORT).show();
Log.i("MYTAG", msg);
}

}


The fragment layout, /res/layout/fragment_layout1.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Fragment 1"/>

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="image_a"/>
<ImageView
android:id="@+id/image_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="image_b"/>
<ImageView
android:id="@+id/image_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="image_c"/>
<ImageView
android:id="@+id/image_c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<TextView
android:id="@+id/textstate"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="image_d"/>
<ImageView
android:id="@+id/image_d"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/loadimage_d"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Load image_d"/>
</LinearLayout>

</LinearLayout>
</ScrollView>

</LinearLayout>


MainActivity.java
package com.example.androidfragmenttest;

import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends MyFragmentActivity {

static public class MyFragment1 extends MyFragment {

ImageView image_b, image_c, image_d;
TextView textState;
Button buttonLoadImage_d;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_layout1, null);

image_b = (ImageView)view.findViewById(R.id.image_b);
image_c = (ImageView)view.findViewById(R.id.image_c);
image_d = (ImageView)view.findViewById(R.id.image_d);
textState = (TextView)view.findViewById(R.id.textstate);
buttonLoadImage_d = (Button)view.findViewById(R.id.loadimage_d);

image_b.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher));

if(savedInstanceState == null){
image_c.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher));
textState.setText("MyFragment1.savedInstanceState == null");
}else{
textState.setText("MyFragment1.savedInstanceState != null");
}

buttonLoadImage_d.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
image_d.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher));
}});

return view;
}

}

FrameLayout fragmentContainer;
Button buttonFinish;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

buttonFinish = (Button)findViewById(R.id.finish);
buttonFinish.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
finish();
}});

fragmentContainer = (FrameLayout) findViewById(R.id.container);
if (savedInstanceState == null) {
// if's the first time created

MyFragment1 myListFragment1 = new MyFragment1();
FragmentManager supportFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = supportFragmentManager
.beginTransaction();
fragmentTransaction.add(R.id.container, myListFragment1);
fragmentTransaction.commit();
}
}

}


Main layout, /res/layout/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >

<Button
android:id="@+id/finish"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="finish()"/>
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>

</LinearLayout>




download filesDownload the files.

No comments:

Post a Comment