实现Fragment->ViewPager->Fragment嵌套,并保存内层Fragment view 状态

来源:互联网 发布:尔雅网络课程怎么快进 编辑:程序博客网 时间:2024/06/07 18:01
前段时间工作中遇到了Fragment->ViewPager->Fragment嵌套的情况,刚开始也没觉得有什么问题,但是测试阶段发现内层Fragment 如果有RecyclerView,并且采用StaggeredGridLayoutManager进行布局,会发现每次切换回来RecyclerView 中item位置会发生偏移。刚开始以为是由于FragmentPagerAdapter的问题导致的(切换时没有存储当前Fragment状态),于是又参照v4包中FragmentStatePagerAdapter重新实现了通用Fragment的相应版本,但是结果还是未达到预期效果(Fragment的状态在viewPager之间切换是可以保存view状态的,但是切换外层Fragment还是不行)。苦思良久无果后,只能源码跟踪,发现原来是外层切换Fragment的时候只是存储当前内层Fragment的了Framgentde 状态,但是其View状态却未保存(这一点是跟ViewPager切换Framement唯一的区别),于是乎开始采取措施,在自己实现FragmentStatePagerAdapter的saveState()中存储添加到FragmentManager中的view状态,然后在restoreState(Parcelable state,ClassLoader loader)中恢复,经过这么一折腾还真达到了目的。特此记录,以备后用。

1、sveState()方法内容如下:

@Override    public Parcelable saveState() {        if (DEBUG) {            Log.d(TAG, "saveState");        }        Bundle state = null;        if (mSavedState.size() > 0) {            state = new Bundle();            Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];            mSavedState.toArray(fss);            state.putParcelableArray("states", fss);        }        for (int i = 0; i < mFragments.size(); i++) {            Fragment f = mFragments.get(i);            if (f != null && f.isAdded()) {                if (state == null) {                    state = new Bundle();                }                String key = "f" + i;                mFragmentManager.putFragment(state, key, f);//                Log.d(TAG, "saveState,i=" + i);                //save fragment view state                Class userCla = (Class) f.getClass().getSuperclass().getSuperclass().getSuperclass().getSuperclass();                Field[] fs = userCla.getDeclaredFields();                for (int k = 0; k < fs.length; k++) {                    Field filed = fs[k];                    filed.setAccessible(true); //设置些属性是可以访问的                    if (TextUtils.equals("mView", filed.getName())) {                        try {                            View view = (View) filed.get(f);                            SparseArray<Parcelable> stateArray = new SparseArray<Parcelable>();                            view.saveHierarchyState(stateArray);                            if (null == state) {                                state = new Bundle();                            }                            state.putSparseParcelableArray("spa:view:" + i, stateArray);//                            Log.d(TAG, "saveViewState+++++++++++++++++++" + stateArray);                        } catch (IllegalAccessException e) {                            e.printStackTrace();                        }                        break;                    }                }                //            }        }        return state;    }

2、restoreState()方法内容如下:

@Override    public void restoreState(Parcelable state, ClassLoader loader) {        if (DEBUG) {            Log.d(TAG, "restoreState");        }        if (state != null) {            Bundle bundle = (Bundle) state;            bundle.setClassLoader(loader);            Parcelable[] fss = bundle.getParcelableArray("states");            mSavedState.clear();            mFragments.clear();            if (fss != null) {                for (int i = 0; i < fss.length; i++) {                    mSavedState.add((Fragment.SavedState) fss[i]);//                    Log.d(TAG, "restoreState,fss,i=" + i + "");                }            }            HashMap<Integer, SparseArray<Parcelable>> fragViewState = new HashMap<Integer, SparseArray<Parcelable>>();            Iterable<String> keys = bundle.keySet();            for (String key : keys) {                if (key.startsWith("spa:view:")) {                    int index = Integer.parseInt(key.substring(9));                    SparseArray<Parcelable> savedViewState = bundle.getSparseParcelableArray("spa:view:" + index);                    if (null != savedViewState) {                        fragViewState.put(index, savedViewState);//                        Log.d(TAG, "restoreState,mFragViewState,index=" + index + ",viewstate="+savedViewState);                    }                }            }            for (String key : keys) {                if (key.startsWith("f")) {                    int index = Integer.parseInt(key.substring(1));                    Fragment f;                    try {                        f = mFragmentManager.getFragment(bundle, key);                        if (f != null) {                            while (mFragments.size() <= index) {                                mFragments.add(null);                            }                            f.setMenuVisibility(false);                            SparseArray<Parcelable> savedViewState = fragViewState.get(index);                            if (null != savedViewState) {                                Class userCla = (Class) f.getClass().getSuperclass().getSuperclass().getSuperclass().getSuperclass();                                Field[] fs = userCla.getDeclaredFields();                                for (int k = 0; k < fs.length; k++) {                                    Field filed = fs[k];                                    filed.setAccessible(true); //设置些属性是可以访问的                                    if (TextUtils.equals("mView", filed.getName())) {                                        try {                                            View view = (View) filed.get(f);                                            if(null != view) {                                                view.restoreHierarchyState(savedViewState);//                                            Log.d(TAG, view + "+++++++++++++++++++");                                            }                                        } catch (IllegalAccessException e) {                                            e.printStackTrace();                                        }                                        break;                                    }                                }                            }                            mFragments.set(index, f);//                            Log.d(TAG, "restoreState,setFragment,i=" + i + "");                        } else {                            Log.w(TAG, "Bad fragment at key " + key);                        }                    } catch (Exception e) {                        Log.w(TAG, "Bad fragment  IllegalStateException" + e.getMessage());                    }                }            }        }    }

1 0
原创粉丝点击