Listview fragment is getting recreated on pressing backbutton
Asked Answered
M

3

3

I'm using loader in my ListView fragment, and it's getting recreated on pressing "back" button. Can you tell me how to handle this senario?

Here is my ListView fragment code. Here I have a boolean variable that I'm setting as true on clicking on list item. but once the back button is pressed onCreateView will get called so the backbutton will be false.

public class GTFragment  extends SherlockFragment implements LoaderCallbacks<Cursor>{

    ListView mTListview = null;
    GoogleTasksAdapter mGTasksAdapter = null;
    private SQLiteCursorLoader mTLoader=null;
    private LoaderManager mTLoaderManager;
    private String mSelectedListID = null; 
    private boolean mIsBackbuttonisPressed = false;

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

    View view = inflater.inflate(R.layout.task_home_activity, container, false);


    if(!mIsBackbuttonisPressed)
        getLoaderManager().initLoader(0, null, this);

     mTListview   = (ListView) view.findViewById(R.id.id_task_list_home_activity);

     mGTasksAdapter = new GoogleTasksAdapter(getActivity());

     mTListview.setOnItemClickListener(new OnItemClickListener() {

         @Override
         public void onItemClick(AdapterView<?> listview,
            View clickedview, int position, long arg3) {
            // TODO Auto-generated method stub

            GoogleTaskItem item = new GoogleTaskItem();

            Cursor coursor = ((GoogleTasksAdapter)listview.getAdapter()).getCursor();



            if(coursor.moveToPosition(position))
            {


                mIsBackbuttonisPressed = true;
                GoogleTaskController.get_googletask_controllerObj()
                  .LaunchTaskPreviewActivity();                 
            }

        }

    });

   mTListview.setAdapter(mGTasksAdapter);  
   mIsBackbuttonisPressed = false;

   return view;

  }

My fragment activity class code

public class TLActivity extends SherlockFragmentActivity {

    LeftSliderTaskListOptions mTaskOptionsFragment = null;
    GoogleTasksFragment mTFragment = null;

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



        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);

        setContentView(R.layout.layout_gt_list);


//      FragmentTransaction tfragment = this.getSupportFragmentManager().beginTransaction();
        mTFragment = new GTasksFragment();
        t.replace(R.id.id_tfragment, mTFragment);
        t.commit();


    }
Mama answered 23/3, 2014 at 10:13 Comment(2)
@NehaShukla, when you edit posts you should improve it as much as you can. You left behind several typos and that glaring enter code here in the beginning.Langan
yes u right..will take careUndernourished
M
0

You have multiple options to rectify this issue.

  1. Override onSaveInstanceState like this:

    @Override
    public void onSaveInstanceState (Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean("mIsBackbuttonisPressed", mIsBackbuttonisPressed);
    }
    

    and then in your onCreateView you can get your variable back by:

    if (savedInstanceState != null)
        mIsBackbuttonisPressed = savedInstanceState.getBoolean("mIsBackbuttonisPressed", false);
    
  2. You can set this.setRetainInstance(true); in your onCreate method of your fragment.

If you could post your Activity code with creates your fragment I can also tell you other options. (P.S I cannot write it as a comment so posting it in the answer.)

Magnanimity answered 23/3, 2014 at 10:51 Comment(20)
Hi, thank you for the answer, when i press the backbutton my whole fragment activity itself is getting recreated, i will be positng you the full code of fragment activity.Mama
hi code is updated, can you please help. i'm creating new activity upon clicking on task list item. Once i press back i'm noticing that my fragment activity is getting recreated, i think its wrong, dont no what is the mistake, if i could avoide that, then my problem would be solved hope so. can you please advice meMama
Could you check that TLActivity onCreate is called after you press back? The reason is that may be the system is destroying your activity. DocumentationMagnanimity
thanks, i;m pretty close to the solution, one more question, if i press back button, then do i have to reload the cursor on listview?. wont the info will be stored in cache?Mama
Yes you have to reload the cursor in onCreate because if the Activity or Fragment is destroyed then the adapter must also be reloaded.Magnanimity
If the answer has helped you then please mark it as solved. ThanksMagnanimity
Hi, thanks, i will definitely mark it. but one more question i would like to know i.e how to store the fragments in onSaveInstanceState? can you post any sample example if you have, thanksMama
You don't have to store fragment. You just have to only override onSaveInstanceState of Fragment in your case because your activity doesn't have any extra data. But if your activity has any extra data then you have to override onSaveInstanceState of your Activity too. BUT you just save DATA in the methods, you don't have to store whole fragment or any kind of view inside those methods.Magnanimity
so, in TLActivity class i dont have to override and save onSaveInstanceState?, only in listfragment i just have to override and store the cursor id to query and restore the item from DB?, is my understanding correct in this case?Mama
Super, thanks lot, it worked like charm :), +1 & marked as right answer now. But one more help, when i press back button i notice that my fragment in TLActivity class is getting recreated always, that does not create problem right?Mama
Hey one more issue, i noticed. If i remove onSaveInstanceState in my activity, then in my fragment if (savedInstanceState != null) is getting called 2 times, why so?Mama
Can we chat here on SO? because I don't think comments are good for discussions. I will solve your issue there.Magnanimity
hi, yes sure.. are u there now. please respond. thanksMama
Yes chat me on stackoverflow. I am online.Magnanimity
Hi, please provide me chat room link,Mama
there is no link in your comment sir, please provide me linkMama
come here, chat.stackoverflow.com/rooms/50220/fragments-life-cycle.. i will be waiting . thanksMama
hey buddy, i got to know where is the issue, its issue with phone, in developer settings i had enabled option to kill activity once it loose focus, developer.android.com/reference/android/app/…. Ondestroy will call only if you call finish() or if system feels ur activity consume more memory then it terminates the activity. else it will be pushed to activity stackMama
I knew that already. But I didn't told you so because that is basically a good thing as it will help you write robust code. Some times the system can kill activities but if you don't handle those scenarios then your app will be unstable.Magnanimity
Yes thats really true, with this i got so many info about the application flow & more concept about the behavior of the activity. Thanks for your support. thank uMama
A
3

instead of

t.replace(R.id.id_tfragment, mTFragment); 

use

t.add(R.id.id_tfragment, mTFragment); 

It worked for me

Anisette answered 25/8, 2015 at 10:39 Comment(0)
A
1

I don't think that the accepted answer is right because Fragment.onSaveInstanceState will not be called until the activity hosting it needs to save its state: The docs states:

There are many situations where a fragment may be mostly torn down (such as when placed on the back stack with no UI showing), but its state will not be saved until its owning activity actually needs to save its state.

In other words: if you're using a Activity with multiple fragments for each screen (which is very common), the fragment state will not be saved when you move the next screen.

You also can't use Fragment.setRetainInstance because he's meant only to fragments that aren't on the back stack.

Most of the time, you don't have to think about this but sometimes it's important. Like when you have scrolled a list and want to "remember" the scroll location.

I took a long time to realize that the fragments put on the back stack are kind of saved and you can reuse the view that you already created instead of creating one every time the fragment calls onCreateView. My setup is something like this:

public abstract class BaseFragment extends Fragment {
     private boolean mSaveView = false;
     private SoftReference<View> mViewReference;

     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          if (mSaveView) {
               if (mViewReference != null) {
                    final View savedView = mViewReference.get();
                    if (savedView != null) {
                         if (savedView.getParent() != null) {
                              ((ViewGroup) savedView.getParent()).removeView(savedView);
                              return savedView;
                         }
                    }
               }
          }

          final View view = inflater.inflate(getFragmentResource(), container, false);
          mViewReference = new SoftReference<View>(view);
          return view;
     }

     protected void setSaveView(boolean value) {
           mSaveView = value;
     }
}

public class MyFragment extends BaseFragment {
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          setSaveView(true);
          final View view = super.onCreateView(inflater, container, savedInstanceState);
          ListView placesList = (ListView) view.findViewById(R.id.places_list);
          if (placesList.getAdapter() == null) { // this check is important so you don't restart your adapter
               placesList.setAdapter(createAdapter());
          }
     }
}
Allative answered 24/9, 2014 at 16:16 Comment(0)
M
0

You have multiple options to rectify this issue.

  1. Override onSaveInstanceState like this:

    @Override
    public void onSaveInstanceState (Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean("mIsBackbuttonisPressed", mIsBackbuttonisPressed);
    }
    

    and then in your onCreateView you can get your variable back by:

    if (savedInstanceState != null)
        mIsBackbuttonisPressed = savedInstanceState.getBoolean("mIsBackbuttonisPressed", false);
    
  2. You can set this.setRetainInstance(true); in your onCreate method of your fragment.

If you could post your Activity code with creates your fragment I can also tell you other options. (P.S I cannot write it as a comment so posting it in the answer.)

Magnanimity answered 23/3, 2014 at 10:51 Comment(20)
Hi, thank you for the answer, when i press the backbutton my whole fragment activity itself is getting recreated, i will be positng you the full code of fragment activity.Mama
hi code is updated, can you please help. i'm creating new activity upon clicking on task list item. Once i press back i'm noticing that my fragment activity is getting recreated, i think its wrong, dont no what is the mistake, if i could avoide that, then my problem would be solved hope so. can you please advice meMama
Could you check that TLActivity onCreate is called after you press back? The reason is that may be the system is destroying your activity. DocumentationMagnanimity
thanks, i;m pretty close to the solution, one more question, if i press back button, then do i have to reload the cursor on listview?. wont the info will be stored in cache?Mama
Yes you have to reload the cursor in onCreate because if the Activity or Fragment is destroyed then the adapter must also be reloaded.Magnanimity
If the answer has helped you then please mark it as solved. ThanksMagnanimity
Hi, thanks, i will definitely mark it. but one more question i would like to know i.e how to store the fragments in onSaveInstanceState? can you post any sample example if you have, thanksMama
You don't have to store fragment. You just have to only override onSaveInstanceState of Fragment in your case because your activity doesn't have any extra data. But if your activity has any extra data then you have to override onSaveInstanceState of your Activity too. BUT you just save DATA in the methods, you don't have to store whole fragment or any kind of view inside those methods.Magnanimity
so, in TLActivity class i dont have to override and save onSaveInstanceState?, only in listfragment i just have to override and store the cursor id to query and restore the item from DB?, is my understanding correct in this case?Mama
Super, thanks lot, it worked like charm :), +1 & marked as right answer now. But one more help, when i press back button i notice that my fragment in TLActivity class is getting recreated always, that does not create problem right?Mama
Hey one more issue, i noticed. If i remove onSaveInstanceState in my activity, then in my fragment if (savedInstanceState != null) is getting called 2 times, why so?Mama
Can we chat here on SO? because I don't think comments are good for discussions. I will solve your issue there.Magnanimity
hi, yes sure.. are u there now. please respond. thanksMama
Yes chat me on stackoverflow. I am online.Magnanimity
Hi, please provide me chat room link,Mama
there is no link in your comment sir, please provide me linkMama
come here, chat.stackoverflow.com/rooms/50220/fragments-life-cycle.. i will be waiting . thanksMama
hey buddy, i got to know where is the issue, its issue with phone, in developer settings i had enabled option to kill activity once it loose focus, developer.android.com/reference/android/app/…. Ondestroy will call only if you call finish() or if system feels ur activity consume more memory then it terminates the activity. else it will be pushed to activity stackMama
I knew that already. But I didn't told you so because that is basically a good thing as it will help you write robust code. Some times the system can kill activities but if you don't handle those scenarios then your app will be unstable.Magnanimity
Yes thats really true, with this i got so many info about the application flow & more concept about the behavior of the activity. Thanks for your support. thank uMama

© 2022 - 2024 — McMap. All rights reserved.