FragmentStatePagerAdapter.java revision 583d8a1ff64c7c59dd4e11759f3d8e994ce878d9
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.support.v4.app;
18
19import android.os.Bundle;
20import android.os.Parcelable;
21import android.support.v4.view.PagerAdapter;
22import android.util.Log;
23import android.view.View;
24import android.view.ViewGroup;
25
26import java.util.ArrayList;
27
28public abstract class FragmentStatePagerAdapter extends PagerAdapter {
29    private static final String TAG = "FragmentStatePagerAdapter";
30    private static final boolean DEBUG = false;
31
32    private final FragmentManager mFragmentManager;
33    private FragmentTransaction mCurTransaction = null;
34
35    private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();
36    private ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
37    private Fragment mCurrentPrimaryItem = null;
38
39    public FragmentStatePagerAdapter(FragmentManager fm) {
40        mFragmentManager = fm;
41    }
42
43    /**
44     * Return the Fragment associated with a specified position.
45     */
46    public abstract Fragment getItem(int position);
47
48    @Override
49    public void startUpdate(ViewGroup container) {
50    }
51
52    @Override
53    public Object instantiateItem(ViewGroup container, int position) {
54        // If we already have this item instantiated, there is nothing
55        // to do.  This can happen when we are restoring the entire pager
56        // from its saved state, where the fragment manager has already
57        // taken care of restoring the fragments we previously had instantiated.
58        if (mFragments.size() > position) {
59            Fragment f = mFragments.get(position);
60            if (f != null) {
61                return f;
62            }
63        }
64
65        if (mCurTransaction == null) {
66            mCurTransaction = mFragmentManager.beginTransaction();
67        }
68
69        Fragment fragment = getItem(position);
70        if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
71        if (mSavedState.size() > position) {
72            Fragment.SavedState fss = mSavedState.get(position);
73            if (fss != null) {
74                fragment.setInitialSavedState(fss);
75            }
76        }
77        while (mFragments.size() <= position) {
78            mFragments.add(null);
79        }
80        fragment.setMenuVisibility(false);
81        mFragments.set(position, fragment);
82        mCurTransaction.add(container.getId(), fragment);
83
84        return fragment;
85    }
86
87    @Override
88    public void destroyItem(ViewGroup container, int position, Object object) {
89        Fragment fragment = (Fragment)object;
90
91        if (mCurTransaction == null) {
92            mCurTransaction = mFragmentManager.beginTransaction();
93        }
94        if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
95                + " v=" + ((Fragment)object).getView());
96        while (mSavedState.size() <= position) {
97            mSavedState.add(null);
98        }
99        mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
100        mFragments.set(position, null);
101
102        mCurTransaction.remove(fragment);
103    }
104
105    @Override
106    public void setPrimaryItem(ViewGroup container, int position, Object object) {
107        Fragment fragment = (Fragment)object;
108        if (fragment != mCurrentPrimaryItem) {
109            if (mCurrentPrimaryItem != null) {
110                mCurrentPrimaryItem.setMenuVisibility(false);
111            }
112            if (fragment != null) {
113                fragment.setMenuVisibility(true);
114            }
115            mCurrentPrimaryItem = fragment;
116        }
117    }
118
119    @Override
120    public void finishUpdate(ViewGroup container) {
121        if (mCurTransaction != null) {
122            mCurTransaction.commitAllowingStateLoss();
123            mCurTransaction = null;
124            mFragmentManager.executePendingTransactions();
125        }
126    }
127
128    @Override
129    public boolean isViewFromObject(View view, Object object) {
130        return ((Fragment)object).getView() == view;
131    }
132
133    @Override
134    public Parcelable saveState() {
135        Bundle state = null;
136        if (mSavedState.size() > 0) {
137            state = new Bundle();
138            Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
139            mSavedState.toArray(fss);
140            state.putParcelableArray("states", fss);
141        }
142        for (int i=0; i<mFragments.size(); i++) {
143            Fragment f = mFragments.get(i);
144            if (f != null) {
145                if (state == null) {
146                    state = new Bundle();
147                }
148                String key = "f" + i;
149                mFragmentManager.putFragment(state, key, f);
150            }
151        }
152        return state;
153    }
154
155    @Override
156    public void restoreState(Parcelable state, ClassLoader loader) {
157        if (state != null) {
158            Bundle bundle = (Bundle)state;
159            bundle.setClassLoader(loader);
160            Parcelable[] fss = bundle.getParcelableArray("states");
161            mSavedState.clear();
162            mFragments.clear();
163            if (fss != null) {
164                for (int i=0; i<fss.length; i++) {
165                    mSavedState.add((Fragment.SavedState)fss[i]);
166                }
167            }
168            Iterable<String> keys = bundle.keySet();
169            for (String key: keys) {
170                if (key.startsWith("f")) {
171                    int index = Integer.parseInt(key.substring(1));
172                    Fragment f = mFragmentManager.getFragment(bundle, key);
173                    if (f != null) {
174                        while (mFragments.size() <= index) {
175                            mFragments.add(null);
176                        }
177                        f.setMenuVisibility(false);
178                        mFragments.set(index, f);
179                    } else {
180                        Log.w(TAG, "Bad fragment at key " + key);
181                    }
182                }
183            }
184        }
185    }
186}
187