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