0

Scenario: Activity A opens Activity B, Activity B has two fragments a and b in a viewpager using FragmentPagerAdapter, fragments a and b has some radio buttons and check boxes where the user interacts with;

I need to store the buttons and checkboxes statuses in the fragments even if I left Activity B to A

My Attempts: 1- removed super.onBack() pressed to force the system into calling onSavedInstanceState in the activity, but still couldn't save fragments to it as am instantiating them in the adapter and do not know how to get the same object created of them to activity

2- tried the onSaveInstanceState(), onViewStateRestored() in each fragment and onSavedInstance never got called using setRetainInstance(true) in the oncreate(); then forced calling onSaveInstanceState() by calling it onPause()

I Read most of available solutions on stack and non of them worked, My Code is as follows;

public class FilterPagerAdapter extends FragmentPagerAdapter {


    public final static int KEYWORDS_TAB = 0;
    public final static int AREAS_TAB = 1;
    private int tabCount;
    private Context context;

public FilterPagerAdapter(FragmentManager fm, int tabCount, Context context) {
    super(fm);
    this.tabCount = tabCount;
    this.context = context;
}


@Override
public Fragment getItem(int position) {
    Fragment fragment;
    switch (position) {
        case KEYWORDS_TAB:
            fragment = KeyWordsFragment.newInstance();
            break;
        case AREAS_TAB:
            fragment = AreasFragment.newInstance();
            break;
        default:
            return null;
    }
    return fragment;
}

@Override
public int getCount() {
    return tabCount;
}

@Override
public CharSequence getPageTitle(int position) {
    String tabTitle = "";
    switch (position) {
        case KEYWORDS_TAB:
            tabTitle = context.getResources().getString(R.string.tab_keywords);
            break;
        case AREAS_TAB:
            tabTitle = context.getResources().getString(R.string.tab_area);
            break;
        default:

    }
    return tabTitle;
}

}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_filters);

    ButterKnife.bind(this);

    mAreas = new Areas();
    mKeywords = new KeyWords();
    viewControllers();
}


private void viewControllers() {

    tabLayout.addTab(tabLayout.newTab().setText(R.string.tab_keywords), CATEGORIES_TAB);
    tabLayout.addTab(tabLayout.newTab().setText(R.string.tab_area), BRANDS_TAB);
    tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
    tabLayout.addOnTabSelectedListener(this);

    filterPagerAdapter = new FilterPagerAdapter(getSupportFragmentManager(),
            tabLayout.getTabCount(), this);
    viewPager.setAdapter(filterPagerAdapter);
    tabLayout.setupWithViewPager(viewPager);
}

@Override
public void onBackPressed() {

    startActivity(new Intent(FiltersActivity.this, BranchesActivity.class));
}


@Override
public void onStop() {
    super.onStop();
    tabLayout.removeOnTabSelectedListener(this);
}

}

aya salama
  • 903
  • 1
  • 10
  • 29

1 Answers1

0

First off, I would recommend not forcing any call to onSavedInstanceState or any of the other lifecycle callbacks. It's better to fit to the flow of the lifecycle than to make the lifecycle fit your flow.

Second, there most likely isn't a reason to use setRetainInstance() on Fragments like this. This method is useful for creating viewless Fragments and store large data-sets. Going beyond that use-case tends to bring a lot of headaches.

So, with those out of the way, there should be a couple of ways to solve this, and they are dependent on the type of data it represents.

Method 1:

One way, which is similar to what you tried with #1, is advance to the next Activity (in this case ActivityA) rather than going back when the user presses back. This will pause and possibly stop ActivityB as well as use the onSaveInstanceState() method in which you can store the state of your Fragments.

The FragmentPagerAdapter will only call getItem() when it needs a new Fragment. All the Fragments that are already created will then be in the FragmentManager. Each Fragment will have to handle its own state. There's no need for the Activity or the Adapter to know about it. Each previously created Fragment will have onSavedInstanceState() called, and the bundle returned from that will be passed in onCreate(bundle) and onCreateView(bundle).

Method 2:

The above works for a lot of cases where the data is not very important. You could get away with it being wiped, and keeping the state is more for convenience. If the user was away from ActivityB for a while for whatever reason, the system could dump it from the stack. If that happens, then it could still be destroyed and the state reverts. In this case, you'll have to use SharedPreferences or some other more permanent data storage to save and restore the state.

Method 3:

I noticed that the name of ActivityB is actually FiltersActivity. I'm making the assumption that FiltersActivity is an Activity in which the user selects filters that get sent back to BranchesActivity. If you don't want to make these persistent, then another method then would be to simply pass the information back and forth between the two.

  1. BranchesActivity will pass in the current filters to FiltersActivity.

  2. FiltersActivity then defaults all its settings to the filters that were passed in.

  3. FiltersActivity lets the user select the new set of filters.

  4. The users presses "back" on FiltersActivity which returns the selected filters.

  5. BranchesActivity now has new filters. When the user wants to change the filters, BranchesActivity will go back to step 1.

Community
  • 1
  • 1
DeeV
  • 35,865
  • 9
  • 108
  • 95
  • First of all Brilliant illustrative answer, secondly I guess the third method is the solution for my case, I'll implement it and get back to you – aya salama Feb 10 '17 at 22:08