Avoiding manually handling configuration changes

自古美人都是妖i 提交于 2019-11-29 16:36:27

You seem to have several issues needed to be fixed.

First your link to mListener in SimpleItemRecyclerViewAdapter gets broken when activity is recreated. Hence you need to restore that connection after activity is recreated. To do that you need to do following fixes.

Main Activity

Make the PageFragmentListener accessible to outside by declaring it as a property

public class MainActivity extends AppCompatActivity implements Bridge {
    ...
    PageChangeListener mListener = new PageChangeListener();
    //keep a reference to listener, need to access this from fragment
    PageFragmentListener mPageFragmentListener;
    ...

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

        mAdapter = new MyAdapter(getSupportFragmentManager());
        //set the listener
        mPageFragmentListener = mAdapter.mListener;
        ....
    }

}

ItemListFragment

Override onActivityCreatedmethod in ItemListFragment and restore mListener by accessing it from the activity

public class ItemListFragment extends BaseFragment{
    ...
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Activity activity = getActivity();
        if(activity instanceof MainActivity) {
            mListener = ((MainActivity)activity).mPageFragmentListener;
    }
    ...
}

Now your mListener will be always set correctly when activity is recreated. But you have to do few more fixes for smoother operation.

Your MyAdapter keep reference to an instance of fragment called mFragment. When activity recreated you need to restore this variable as well. Hence you need to modify your MyAdapter constructor as below.

public MyAdapter(FragmentManager fm) {
    super(fm);
    mFragmentManager = fm;
    List<Fragment> fragments = fm.getFragments();
    if(fragments != null) {
        for (Fragment f : fragments) {
            if (f instanceof ItemListFragment || f instanceof ItemOneDetailFragment) {
                mFragment = (BaseFragment) f;
            }
        }
    }
}

At this point your code should work. But it will crash when you rotate your device while viewing the detail of a list item. This happens because you add child fragments to the activity directly from your ItemListFragment using the Activity's FragmentManager. Instead use childFragmentManager from Fragment itself.

holder.mView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mTwoPane) {     // landscape mode
        ...
        // show detail fragment to right side of screen
        getChildFragmentManager().beginTransaction()
            .replace(R.id.item_detail_container, fragment)
            .commit();
        } else {    // portrait mode
            ...
        }
    }
});

Using the MVP pattern might help since Presenters can be created in a way such that they survive configuration changes. I recently came across a series of blog posts aimed at explaining such an implementation of the MVP pattern. I'm sure they'll be of help to you.

Blogs posts: Part 1 Part 2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!