FragmentManager.java revision f121be737c59390d97e21a92be8e166001534c7d
12dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn/* 22dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * Copyright (C) 2010 The Android Open Source Project 32dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * 42dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 52dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * you may not use this file except in compliance with the License. 62dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * You may obtain a copy of the License at 72dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * 82dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 92dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * 102dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * Unless required by applicable law or agreed to in writing, software 112dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 122dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * See the License for the specific language governing permissions and 142dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * limitations under the License. 152dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn */ 162dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 172dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackbornpackage android.app; 182dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 19f121be737c59390d97e21a92be8e166001534c7dDianne Hackbornimport android.content.res.TypedArray; 202dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackbornimport android.os.Bundle; 21ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackbornimport android.os.Handler; 222dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackbornimport android.view.ViewGroup; 23f121be737c59390d97e21a92be8e166001534c7dDianne Hackbornimport android.view.animation.Animation; 24f121be737c59390d97e21a92be8e166001534c7dDianne Hackbornimport android.view.animation.AnimationUtils; 252dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 262dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackbornimport java.util.ArrayList; 272dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 28ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborninterface BackStackState { 29ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn public void popFromBackStack(); 30f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn public String getName(); 31f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn public int getTransition(); 32f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn public int getTransitionStyle(); 33ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn} 34ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn 352dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn/** 36f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn * @hide 372dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn * Container for fragments associated with an activity. 382dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn */ 39f121be737c59390d97e21a92be8e166001534c7dDianne Hackbornpublic class FragmentManager { 40ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn ArrayList<Fragment> mFragments; 41ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn ArrayList<BackStackState> mBackStack; 422dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 432dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn int mCurState = Fragment.INITIALIZING; 442dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn Activity mActivity; 452dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 46f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn Animation loadAnimation(Fragment fragment, int transit, boolean enter, 47f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn int transitionStyle) { 48f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn Animation animObj = fragment.onCreateAnimation(transitionStyle, enter); 49f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (animObj != null) { 50f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn return animObj; 51f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 52f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn 53f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (transit == 0) { 54f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn return null; 55f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 56f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn 57f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn int styleIndex = transitToStyleIndex(transit, enter); 58f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (styleIndex < 0) { 59f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn return null; 60f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 61f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn 62f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (transitionStyle == 0 && mActivity.getWindow() != null) { 63f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn transitionStyle = mActivity.getWindow().getAttributes().windowAnimations; 64f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 65f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (transitionStyle == 0) { 66f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn return null; 67f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 68f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn 69f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn TypedArray attrs = mActivity.obtainStyledAttributes(transitionStyle, 70f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn com.android.internal.R.styleable.WindowAnimation); 71f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn int anim = attrs.getResourceId(styleIndex, 0); 72f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn attrs.recycle(); 73f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn 74f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (anim == 0) { 75f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn return null; 76f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 77f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn 78f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn return AnimationUtils.loadAnimation(mActivity, anim); 79f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 80f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn 81f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn void moveToState(Fragment f, int newState, int transit, int transitionStyle) { 822dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (f.mState < newState) { 832dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn switch (f.mState) { 842dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn case Fragment.INITIALIZING: 852dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mActivity = mActivity; 862dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mCalled = false; 872dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.onAttach(mActivity); 882dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (!f.mCalled) { 892dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn throw new SuperNotCalledException("Fragment " + f 902dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn + " did not call through to super.onAttach()"); 912dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 922dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mCalled = false; 932dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.onCreate(null); 942dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (!f.mCalled) { 952dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn throw new SuperNotCalledException("Fragment " + f 962dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn + " did not call through to super.onCreate()"); 972dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 982dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 992dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn ViewGroup container = null; 1002dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (f.mContainerId != 0) { 1012dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn container = (ViewGroup)mActivity.findViewById(f.mContainerId); 1022dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (container == null) { 1032dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn throw new IllegalArgumentException("New view found for id 0x" 1042dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn + Integer.toHexString(f.mContainerId) 1052dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn + " for fragment " + f); 1062dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1072dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1082dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mContainer = container; 1092dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mView = f.onCreateView(mActivity.getLayoutInflater(), container); 1102dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (container != null && f.mView != null) { 111f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn Animation anim = loadAnimation(f, transit, true, transitionStyle); 112f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (anim != null) { 113f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn f.mView.setAnimation(anim); 114f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 1152dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn container.addView(f.mView); 1162dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1172dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 1182dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn case Fragment.CREATED: 1192dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (newState > Fragment.CREATED) { 1202dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mCalled = false; 1212dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.onStart(); 1222dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (!f.mCalled) { 1232dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn throw new SuperNotCalledException("Fragment " + f 1242dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn + " did not call through to super.onStart()"); 1252dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1262dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1272dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn case Fragment.STARTED: 1282dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (newState > Fragment.STARTED) { 1292dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mCalled = false; 1302dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.onResume(); 1312dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (!f.mCalled) { 1322dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn throw new SuperNotCalledException("Fragment " + f 1332dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn + " did not call through to super.onResume()"); 1342dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1352dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1362dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1372dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } else if (f.mState > newState) { 1382dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn switch (f.mState) { 1392dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn case Fragment.RESUMED: 1402dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (newState < Fragment.RESUMED) { 1412dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mCalled = false; 1422dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.onPause(); 1432dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (!f.mCalled) { 1442dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn throw new SuperNotCalledException("Fragment " + f 1452dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn + " did not call through to super.onPause()"); 1462dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1472dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1482dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn case Fragment.STARTED: 1492dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (newState < Fragment.STARTED) { 1502dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mCalled = false; 1512dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.onStop(); 1522dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (!f.mCalled) { 1532dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn throw new SuperNotCalledException("Fragment " + f 1542dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn + " did not call through to super.onStop()"); 1552dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1562dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1572dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn case Fragment.CREATED: 1582dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (newState < Fragment.CREATED) { 159f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (f.mContainer != null) { 160f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn Animation anim = loadAnimation(f, transit, false, transitionStyle); 161f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (anim != null) { 162f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn f.mView.setAnimation(anim); 163f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 1642dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mContainer.removeView(f.mView); 1652dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1662dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mContainer = null; 1672dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mView = null; 1682dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 1692dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mCalled = false; 1702dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.onDestroy(); 1712dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (!f.mCalled) { 1722dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn throw new SuperNotCalledException("Fragment " + f 1732dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn + " did not call through to super.onDestroy()"); 1742dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1752dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mCalled = false; 1762dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.onDetach(); 1772dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (!f.mCalled) { 1782dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn throw new SuperNotCalledException("Fragment " + f 1792dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn + " did not call through to super.onDetach()"); 1802dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1812dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mActivity = null; 1822dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1832dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1842dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1852dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 1862dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn f.mState = newState; 1872dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1882dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 189ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn void moveToState(int newState, boolean always) { 190f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn moveToState(newState, 0, 0, always); 191f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 192f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn 193f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn void moveToState(int newState, int transit, int transitStyle, boolean always) { 1942dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (mActivity == null && newState != Fragment.INITIALIZING) { 1952dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn throw new IllegalStateException("No activity"); 1962dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 1972dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 198ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn if (!always && mCurState == newState) { 199ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn return; 200ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn } 201ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn 2022dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn mCurState = newState; 203ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn if (mFragments != null) { 204ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn for (int i=0; i<mFragments.size(); i++) { 205ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn Fragment f = mFragments.get(i); 206f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn moveToState(f, newState, transit, transitStyle); 207ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn } 2082dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 2092dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 2102dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 211ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn public void addFragment(Fragment fragment, boolean moveToStateNow) { 212ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn if (mFragments == null) { 213ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn mFragments = new ArrayList<Fragment>(); 214ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn } 2152dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn mFragments.add(fragment); 216ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn if (moveToStateNow) { 217f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn moveToState(fragment, mCurState, 0, 0); 218ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn } 2192dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 2202dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 221f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn public void removeFragment(Fragment fragment, int transition, int transitionStyle) { 2222dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn mFragments.remove(fragment); 223f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn moveToState(fragment, Fragment.INITIALIZING, transition, transitionStyle); 224f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 225f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn 226f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn public Fragment findFragmentById(int id) { 227f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (mFragments != null) { 228f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn for (int i=mFragments.size()-1; i>=0; i--) { 229f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn Fragment f = mFragments.get(i); 230f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (f.mContainerId == id) { 231f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn return f; 232f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 233f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 234f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 235f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn return null; 2362dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 2372dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 238ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn public void addBackStackState(BackStackState state) { 239ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn if (mBackStack == null) { 240ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn mBackStack = new ArrayList<BackStackState>(); 241ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn } 242ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn mBackStack.add(state); 243ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn } 244ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn 245f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn public boolean popBackStackState(Handler handler, String name) { 246ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn if (mBackStack == null) { 247ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn return false; 248ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn } 249f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (name == null) { 250f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn int last = mBackStack.size()-1; 251f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (last < 0) { 252f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn return false; 253f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 254f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn final BackStackState bss = mBackStack.remove(last); 255f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn handler.post(new Runnable() { 256f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn public void run() { 257f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn bss.popFromBackStack(); 258f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn moveToState(mCurState, reverseTransit(bss.getTransition()), 259f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn bss.getTransitionStyle(), true); 260f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 261f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn }); 262f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } else { 263f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn int index = mBackStack.size()-1; 264f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn while (index >= 0) { 265f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn BackStackState bss = mBackStack.get(index); 266f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (name.equals(bss.getName())) { 267f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 268f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 269f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 270f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn if (index < 0 || index == mBackStack.size()-1) { 271f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn return false; 272f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 273f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn final ArrayList<BackStackState> states = new ArrayList<BackStackState>(); 274f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn for (int i=mBackStack.size()-1; i>index; i--) { 275f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn states.add(mBackStack.remove(i)); 276ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn } 277f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn handler.post(new Runnable() { 278f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn public void run() { 279f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn for (int i=0; i<states.size(); i++) { 280f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn states.get(i).popFromBackStack(); 281f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 282f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn moveToState(mCurState, true); 283f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 284f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn }); 285f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 286ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn return true; 287ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn } 288ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn 2892dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn public void attachActivity(Activity activity) { 2902dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn if (mActivity != null) throw new IllegalStateException(); 2912dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn mActivity = activity; 2922dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 2932dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 2942dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn public void dispatchCreate(Bundle state) { 295ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn moveToState(Fragment.CREATED, false); 2962dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 2972dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 2982dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn public void dispatchStart() { 299ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn moveToState(Fragment.STARTED, false); 3002dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 3012dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 3022dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn public void dispatchResume() { 303ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn moveToState(Fragment.RESUMED, false); 3042dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 3052dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 3062dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn public void dispatchPause() { 307ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn moveToState(Fragment.STARTED, false); 3082dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 3092dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 3102dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn public void dispatchStop() { 311ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn moveToState(Fragment.CREATED, false); 3122dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 3132dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn 3142dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn public void dispatchDestroy() { 315ba51c3d02d08709e933de6f6c76dee3fd2f4bfa1Dianne Hackborn moveToState(Fragment.INITIALIZING, false); 3162dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn mActivity = null; 3172dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn } 318f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn 319f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn public static int reverseTransit(int transit) { 320f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn int rev = 0; 321f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn switch (transit) { 322f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_ENTER: 323f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_EXIT; 324f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 325f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_EXIT: 326f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_ENTER; 327f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 328f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_SHOW: 329f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_HIDE; 330f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 331f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_HIDE: 332f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_SHOW; 333f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 334f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_ACTIVITY_OPEN: 335f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_ACTIVITY_CLOSE; 336f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 337f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_ACTIVITY_CLOSE: 338f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_ACTIVITY_OPEN; 339f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 340f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_TASK_OPEN: 341f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_TASK_CLOSE; 342f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 343f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_TASK_CLOSE: 344f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_TASK_OPEN; 345f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 346f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_TASK_TO_FRONT: 347f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_TASK_TO_BACK; 348f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 349f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_TASK_TO_BACK: 350f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_TASK_TO_FRONT; 351f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 352f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_WALLPAPER_OPEN: 353f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_WALLPAPER_CLOSE; 354f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 355f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_WALLPAPER_CLOSE: 356f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_WALLPAPER_OPEN; 357f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 358f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_WALLPAPER_INTRA_OPEN: 359f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_WALLPAPER_INTRA_CLOSE; 360f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 361f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_WALLPAPER_INTRA_CLOSE: 362f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn rev = FragmentTransaction.TRANSIT_WALLPAPER_INTRA_OPEN; 363f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 364f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 365f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn return rev; 366f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn 367f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 368f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn 369f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn public static int transitToStyleIndex(int transit, boolean enter) { 370f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn int animAttr = -1; 371f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn switch (transit) { 372f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_ENTER: 373f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation; 374f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 375f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_EXIT: 376f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation; 377f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 378f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_SHOW: 379f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation; 380f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 381f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_HIDE: 382f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation; 383f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 384f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_ACTIVITY_OPEN: 385f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = enter 386f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation 387f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation; 388f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 389f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_ACTIVITY_CLOSE: 390f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = enter 391f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation 392f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation; 393f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 394f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_TASK_OPEN: 395f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = enter 396f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation 397f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation; 398f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 399f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_TASK_CLOSE: 400f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = enter 401f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation 402f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation; 403f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 404f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_TASK_TO_FRONT: 405f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = enter 406f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation 407f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation; 408f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 409f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_TASK_TO_BACK: 410f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = enter 411f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation 412f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation; 413f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 414f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_WALLPAPER_OPEN: 415f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = enter 416f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation 417f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation; 418f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 419f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_WALLPAPER_CLOSE: 420f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = enter 421f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation 422f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation; 423f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 424f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_WALLPAPER_INTRA_OPEN: 425f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = enter 426f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation 427f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation; 428f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 429f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn case FragmentTransaction.TRANSIT_WALLPAPER_INTRA_CLOSE: 430f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn animAttr = enter 431f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation 432f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation; 433f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn break; 434f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 435f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn return animAttr; 436f121be737c59390d97e21a92be8e166001534c7dDianne Hackborn } 4372dedce6e84679ead961a485c7fe4b0f77c713b6aDianne Hackborn} 438