FragmentManager.popBackStack() does not simply loads the previous Fragment

13,152

Solution 1

Your design pattern is flawed due to a poor separation of concerns. The updating of data should be decoupled from the UI, therfore when a user goes back to the previous Fragment it should have nothing to do with loading data from a web service.

There are a couple of easy fixes but I do not know what will work best as you have given little context to the problem.

First option would be to introduce a Splash Screen on start up. This Activity would make use of an AsyncTask to download the data you need from the web service. This works well if you only want the data to be downloaded once during the runtime of the app. You would make sure not to add this Activity to the history so when back is pressed from the next activity, the app would then exit.

Another option, which I have used in many apps and the one I prefer, is the use of Alarms via the AlarmManager. You can set a periodic updates at specific time intervals, the AlarmManager even helps you to the point where it contains enumerations of time. The Alarm will trigger a broadcast receiver which will execute your custom code, that will download the data you need from the web service and store it.

There is a tutorial on this approach, which can be found here http://android.arnodenhond.com/tutorials/alarm-notification.

Finally; you should not need to pop the back stack to get around this problem, although you might be doing this for entirely different reasons but it is hard to tell without more info.

Solution 2

Your question is not clear enough, ask more simple and precise questions... And as you say above

popBackStack does not load the last fragment, it's commonly used to pop the entire stack :

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 

before loading another fragment

beginTransaction()
replace() Or add()
commit()

That's all i can think about with that question

Good luck

Share:
13,152
Aamir
Author by

Aamir

Just another software engineer

Updated on June 06, 2022

Comments

  • Aamir
    Aamir almost 2 years

    I have a main TabActivity which has two tabs, A and B (for now). Tab A loads a FragmentActivity (code given below) which just conatains a FrameLayout, so I can load my Fragments for that specific Tab in it.

    The first Fragment has some TextViews and one ListView. Data is pulled from a web service. When I click on an ListView's item, I load that item's detail in another Fragment (this also comes from a web service) and replace the current Fragment (with ListView and other controls) with another detail fragment.

    To achieve this, I am using android-support-v4.jar library to use Fragments as they were preferred.

    Tab A's FragmentActivity's XML:

    <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical" >
    
            <FrameLayout
                android:id="@+id/updates_frame"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:background="@drawable/background"/>
        </LinearLayout>
    

    Tab A's FragmentActivity Java code:

    public class UpdatesFragmentActivity extends FragmentActivity implements
        IUpdateNotifier {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.updates);
    
            //Load Initial Fragment into FrameLayout
            //I am adding this Fragment to BackStack
            Fragment newFragment = new UpdatesFragment();
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.addToBackStack(null);
            ft.add(R.id.updates_frame, newFragment);
            ft.commit();
        }
    
        //This is an Interface method which I call with the clicked "FEED" object to load its detail in another Fragment
        @Override
        public void onFeedSelected(Feed feed) {
            // Instantiate a new fragment.
            Fragment newFragment = new FeedDetailFragment(feed);
    
            // Add the fragment to the activity, pushing this transaction
            // on to the back stack.
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.updates_frame, newFragment);
            ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
            ft.addToBackStack(null);
            ft.commit();
        }
    
        //This is another Interface Method which I call when the user presses "BACK".
        //I am trying to load the previously loaded Fragment, which I added to BackStack.
        //But this causes reconstruction of the previously loaded fragment. LIST in this case
        //which call the web service. I DONT WANT TO CALL SERVICE AGAIN.
        @Override
        public void onBackPressed() {
            FragmentManager fm = getSupportFragmentManager();
            if (fm.getBackStackEntryCount() > 0) {
                fm.popBackStack();
            }
        }
    }
    

    I have created an interface IUpdateNotifier, which contains two methods:

    public void onFeedSelected(Feed feed);
    public void onBackPressed();
    

    Parent UpdatesFragmentActivity implements these methods. I call these methods from children Fragments upon following actions.

    1. I call onFeedSelected(Feed feed) from the Fragment which has a ListView. I send the clicked feed item to parent FragmentActivity, so it loads another Fragment which would contain that feed detail.
    2. I call onBackPressed() from the second feed detail Fragment when the user presses a button that is supposed to bring back the first fragment which contained ListView with other controls. As you can see, I try to call FragmentManager's popBackStack() method to bring back that first Fragment...

    But the first Fragment gets refreshed and loads all the data from web service.

    Actually I cannot get and store data only once nor the updates are frequent on some time intervals. The user can update the list when he wants. Initially, the list loads the top 10 items from the service, and then user can click the "More" button at the end of list if he wants to load more items.

    It will load the next 10 items and so on. But I think I can store the retrieved ArrayList in some variable in UpdatesFragmentActivity and then just reassign that ArrayList to the list's adapter instead of loading the data from service, but I don't know how to make Fragment not to call service again.

    I want it to behave like when I click on tab 2 and then on tab 1 again. It simply shows the loaded data as if was hidden and does not call the service.

    How can I achieve this?

  • Aamir
    Aamir about 12 years
    I am really sorry for not providing enough info about the issue i am facing. I have updated my question ... u can have a look at it now ... i have tried to explain my issue.
  • Graham Smith
    Graham Smith about 12 years
    I am not altering my answer as I do not agree that you have chosen the best approach. The answer above should steer you in the right direction.
  • Aamir
    Aamir about 12 years
    Actually i cannot get & store data only once nor the updates are frequent on some time inervals , user can update the list when he wants.. Initially the list loads the top 10 items from the service, then user can click "More" button at the end of list if he wants to load more items. it will load the next 10 items.. and so on. Tough i appreciate that u pointed me to AlarmManager which i migh use in some scenario where periodic updates are required but i dont think i can use the AlarmManager in this situation.. But i think i can store the retrieved ArrayList in some variable in FragmentActivity.
  • Aamir
    Aamir about 12 years
    And then just reassign that ArrayList to list's adapter instead of loading the data from service ... but i dont know how to make Fragment not to call service again. U can help me achieve this as i am stuck .. and if u understand my scenario now then u can guide me to some best approach. i will really appreciate as am new to android. thanks
  • JWqvist
    JWqvist over 10 years
    My solution was fragmentManager.popBackStack(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);
  • tad
    tad over 10 years
    No. Never use AlarmManager to schedule regularly recurring tasks that only matter while a certain fragment is displaying. See the docs at developer.android.com/reference/android/app/AlarmManager.htm‌​l