FragmentManager.java revision ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1
1/*
2 * Copyright (C) 2010 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.app;
18
19import android.os.Bundle;
20import android.os.Handler;
21import android.view.ViewGroup;
22
23import java.util.ArrayList;
24
25interface BackStackState {
26    public void popFromBackStack();
27}
28
29/**
30 * Container for fragments associated with an activity.
31 */
32class FragmentManager {
33    ArrayList<Fragment> mFragments;
34    ArrayList<BackStackState> mBackStack;
35
36    int mCurState = Fragment.INITIALIZING;
37    Activity mActivity;
38
39    void moveToState(Fragment f, int newState) {
40        if (f.mState < newState) {
41            switch (f.mState) {
42                case Fragment.INITIALIZING:
43                    f.mActivity = mActivity;
44                    f.mCalled = false;
45                    f.onAttach(mActivity);
46                    if (!f.mCalled) {
47                        throw new SuperNotCalledException("Fragment " + f
48                                + " did not call through to super.onAttach()");
49                    }
50                    f.mCalled = false;
51                    f.onCreate(null);
52                    if (!f.mCalled) {
53                        throw new SuperNotCalledException("Fragment " + f
54                                + " did not call through to super.onCreate()");
55                    }
56
57                    ViewGroup container = null;
58                    if (f.mContainerId != 0) {
59                        container = (ViewGroup)mActivity.findViewById(f.mContainerId);
60                        if (container == null) {
61                            throw new IllegalArgumentException("New view found for id 0x"
62                                    + Integer.toHexString(f.mContainerId)
63                                    + " for fragment " + f);
64                        }
65                    }
66                    f.mContainer = container;
67                    f.mView = f.onCreateView(mActivity.getLayoutInflater(), container);
68                    if (container != null && f.mView != null) {
69                        container.addView(f.mView);
70                    }
71
72                case Fragment.CREATED:
73                    if (newState > Fragment.CREATED) {
74                        f.mCalled = false;
75                        f.onStart();
76                        if (!f.mCalled) {
77                            throw new SuperNotCalledException("Fragment " + f
78                                    + " did not call through to super.onStart()");
79                        }
80                    }
81                case Fragment.STARTED:
82                    if (newState > Fragment.STARTED) {
83                        f.mCalled = false;
84                        f.onResume();
85                        if (!f.mCalled) {
86                            throw new SuperNotCalledException("Fragment " + f
87                                    + " did not call through to super.onResume()");
88                        }
89                    }
90            }
91        } else if (f.mState > newState) {
92            switch (f.mState) {
93                case Fragment.RESUMED:
94                    if (newState < Fragment.RESUMED) {
95                        f.mCalled = false;
96                        f.onPause();
97                        if (!f.mCalled) {
98                            throw new SuperNotCalledException("Fragment " + f
99                                    + " did not call through to super.onPause()");
100                        }
101                    }
102                case Fragment.STARTED:
103                    if (newState < Fragment.STARTED) {
104                        f.mCalled = false;
105                        f.onStop();
106                        if (!f.mCalled) {
107                            throw new SuperNotCalledException("Fragment " + f
108                                    + " did not call through to super.onStop()");
109                        }
110                    }
111                case Fragment.CREATED:
112                    if (newState < Fragment.CREATED) {
113                        if (f.mContainer != null && f.mView != null) {
114                            f.mContainer.removeView(f.mView);
115                        }
116                        f.mContainer = null;
117                        f.mView = null;
118
119                        f.mCalled = false;
120                        f.onDestroy();
121                        if (!f.mCalled) {
122                            throw new SuperNotCalledException("Fragment " + f
123                                    + " did not call through to super.onDestroy()");
124                        }
125                        f.mCalled = false;
126                        f.onDetach();
127                        if (!f.mCalled) {
128                            throw new SuperNotCalledException("Fragment " + f
129                                    + " did not call through to super.onDetach()");
130                        }
131                        f.mActivity = null;
132                    }
133            }
134        }
135
136        f.mState = newState;
137    }
138
139    void moveToState(int newState, boolean always) {
140        if (mActivity == null && newState != Fragment.INITIALIZING) {
141            throw new IllegalStateException("No activity");
142        }
143
144        if (!always && mCurState == newState) {
145            return;
146        }
147
148        mCurState = newState;
149        if (mFragments != null) {
150            for (int i=0; i<mFragments.size(); i++) {
151                Fragment f = mFragments.get(i);
152                moveToState(f, newState);
153            }
154        }
155    }
156
157    public void addFragment(Fragment fragment, boolean moveToStateNow) {
158        if (mFragments == null) {
159            mFragments = new ArrayList<Fragment>();
160        }
161        mFragments.add(fragment);
162        if (moveToStateNow) {
163            moveToState(fragment, mCurState);
164        }
165    }
166
167    public void removeFragment(Fragment fragment) {
168        mFragments.remove(fragment);
169        moveToState(fragment, Fragment.INITIALIZING);
170    }
171
172    public void addBackStackState(BackStackState state) {
173        if (mBackStack == null) {
174            mBackStack = new ArrayList<BackStackState>();
175        }
176        mBackStack.add(state);
177    }
178
179    public boolean popBackStackState(Handler handler) {
180        if (mBackStack == null) {
181            return false;
182        }
183        int last = mBackStack.size()-1;
184        if (last < 0) {
185            return false;
186        }
187        final BackStackState bss = mBackStack.remove(last);
188        handler.post(new Runnable() {
189            public void run() {
190                bss.popFromBackStack();
191            }
192        });
193        return true;
194    }
195
196    public void attachActivity(Activity activity) {
197        if (mActivity != null) throw new IllegalStateException();
198        mActivity = activity;
199    }
200
201    public void dispatchCreate(Bundle state) {
202        moveToState(Fragment.CREATED, false);
203    }
204
205    public void dispatchStart() {
206        moveToState(Fragment.STARTED, false);
207    }
208
209    public void dispatchResume() {
210        moveToState(Fragment.RESUMED, false);
211    }
212
213    public void dispatchPause() {
214        moveToState(Fragment.STARTED, false);
215    }
216
217    public void dispatchStop() {
218        moveToState(Fragment.CREATED, false);
219    }
220
221    public void dispatchDestroy() {
222        moveToState(Fragment.INITIALIZING, false);
223        mActivity = null;
224    }
225}
226