blob: 351e7379a36c10132f9daa6fac3c96ec152321ed [file] [log] [blame]
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001/*
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
Clara Bayarricd916f22016-06-13 13:14:51 +010019import android.os.Build;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070020import android.os.Parcel;
21import android.os.Parcelable;
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070022import android.text.TextUtils;
Dianne Hackborn445646c2010-06-25 15:52:59 -070023import android.util.Log;
Dianne Hackbornf43a33c2012-09-27 00:48:11 -070024import android.util.LogWriter;
George Mountd4c3c912014-06-09 12:31:34 -070025import android.view.View;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070026
George Mounta7245b42016-02-10 17:03:32 -080027import com.android.internal.util.FastPrintWriter;
28
Dianne Hackborn30d71892010-12-11 10:37:55 -080029import java.io.FileDescriptor;
30import java.io.PrintWriter;
Clara Bayarricd916f22016-06-13 13:14:51 +010031import java.lang.reflect.Modifier;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070032import java.util.ArrayList;
33
34final class BackStackState implements Parcelable {
35 final int[] mOps;
36 final int mTransition;
37 final int mTransitionStyle;
38 final String mName;
Dianne Hackborndd913a52010-07-22 12:17:04 -070039 final int mIndex;
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070040 final int mBreadCrumbTitleRes;
41 final CharSequence mBreadCrumbTitleText;
42 final int mBreadCrumbShortTitleRes;
43 final CharSequence mBreadCrumbShortTitleText;
George Mountd4c3c912014-06-09 12:31:34 -070044 final ArrayList<String> mSharedElementSourceNames;
45 final ArrayList<String> mSharedElementTargetNames;
George Mounta0ffaff2017-04-26 13:10:59 -070046 final boolean mReorderingAllowed;
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070047
48 public BackStackState(FragmentManagerImpl fm, BackStackRecord bse) {
George Mountf2045f82016-06-27 13:15:01 -070049 final int numOps = bse.mOps.size();
50 mOps = new int[numOps * 6];
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070051
Dianne Hackbornb7a2e472010-08-12 16:20:42 -070052 if (!bse.mAddToBackStack) {
53 throw new IllegalStateException("Not on back stack");
54 }
55
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070056 int pos = 0;
George Mountf2045f82016-06-27 13:15:01 -070057 for (int opNum = 0; opNum < numOps; opNum++) {
58 final BackStackRecord.Op op = bse.mOps.get(opNum);
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070059 mOps[pos++] = op.cmd;
Dianne Hackbornee76efb2012-06-05 10:27:40 -070060 mOps[pos++] = op.fragment != null ? op.fragment.mIndex : -1;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070061 mOps[pos++] = op.enterAnim;
62 mOps[pos++] = op.exitAnim;
Chet Haasebc377842011-03-22 11:35:22 -070063 mOps[pos++] = op.popEnterAnim;
64 mOps[pos++] = op.popExitAnim;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070065 }
66 mTransition = bse.mTransition;
67 mTransitionStyle = bse.mTransitionStyle;
68 mName = bse.mName;
Dianne Hackborndd913a52010-07-22 12:17:04 -070069 mIndex = bse.mIndex;
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070070 mBreadCrumbTitleRes = bse.mBreadCrumbTitleRes;
71 mBreadCrumbTitleText = bse.mBreadCrumbTitleText;
72 mBreadCrumbShortTitleRes = bse.mBreadCrumbShortTitleRes;
73 mBreadCrumbShortTitleText = bse.mBreadCrumbShortTitleText;
George Mountd4c3c912014-06-09 12:31:34 -070074 mSharedElementSourceNames = bse.mSharedElementSourceNames;
75 mSharedElementTargetNames = bse.mSharedElementTargetNames;
George Mounta0ffaff2017-04-26 13:10:59 -070076 mReorderingAllowed = bse.mReorderingAllowed;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070077 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070078
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070079 public BackStackState(Parcel in) {
80 mOps = in.createIntArray();
81 mTransition = in.readInt();
82 mTransitionStyle = in.readInt();
83 mName = in.readString();
Dianne Hackborndd913a52010-07-22 12:17:04 -070084 mIndex = in.readInt();
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070085 mBreadCrumbTitleRes = in.readInt();
86 mBreadCrumbTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
87 mBreadCrumbShortTitleRes = in.readInt();
88 mBreadCrumbShortTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
George Mountd4c3c912014-06-09 12:31:34 -070089 mSharedElementSourceNames = in.createStringArrayList();
90 mSharedElementTargetNames = in.createStringArrayList();
George Mounta0ffaff2017-04-26 13:10:59 -070091 mReorderingAllowed = in.readInt() != 0;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070092 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070093
94 public BackStackRecord instantiate(FragmentManagerImpl fm) {
95 BackStackRecord bse = new BackStackRecord(fm);
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070096 int pos = 0;
Dianne Hackbornf43a33c2012-09-27 00:48:11 -070097 int num = 0;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070098 while (pos < mOps.length) {
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070099 BackStackRecord.Op op = new BackStackRecord.Op();
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700100 op.cmd = mOps[pos++];
George Mountd4c3c912014-06-09 12:31:34 -0700101 if (FragmentManagerImpl.DEBUG) {
102 Log.v(FragmentManagerImpl.TAG,
103 "Instantiate " + bse + " op #" + num + " base fragment #" + mOps[pos]);
104 }
Dianne Hackbornee76efb2012-06-05 10:27:40 -0700105 int findex = mOps[pos++];
106 if (findex >= 0) {
107 Fragment f = fm.mActive.get(findex);
108 op.fragment = f;
109 } else {
110 op.fragment = null;
111 }
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700112 op.enterAnim = mOps[pos++];
113 op.exitAnim = mOps[pos++];
Chet Haasebc377842011-03-22 11:35:22 -0700114 op.popEnterAnim = mOps[pos++];
115 op.popExitAnim = mOps[pos++];
George Mount41fb9942016-03-30 13:59:23 -0700116 bse.mEnterAnim = op.enterAnim;
117 bse.mExitAnim = op.exitAnim;
118 bse.mPopEnterAnim = op.popEnterAnim;
119 bse.mPopExitAnim = op.popExitAnim;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700120 bse.addOp(op);
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700121 num++;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700122 }
123 bse.mTransition = mTransition;
124 bse.mTransitionStyle = mTransitionStyle;
125 bse.mName = mName;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700126 bse.mIndex = mIndex;
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700127 bse.mAddToBackStack = true;
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700128 bse.mBreadCrumbTitleRes = mBreadCrumbTitleRes;
129 bse.mBreadCrumbTitleText = mBreadCrumbTitleText;
130 bse.mBreadCrumbShortTitleRes = mBreadCrumbShortTitleRes;
131 bse.mBreadCrumbShortTitleText = mBreadCrumbShortTitleText;
George Mountd4c3c912014-06-09 12:31:34 -0700132 bse.mSharedElementSourceNames = mSharedElementSourceNames;
133 bse.mSharedElementTargetNames = mSharedElementTargetNames;
George Mounta0ffaff2017-04-26 13:10:59 -0700134 bse.mReorderingAllowed = mReorderingAllowed;
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700135 bse.bumpBackStackNesting(1);
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700136 return bse;
137 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700138
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700139 public int describeContents() {
140 return 0;
141 }
142
143 public void writeToParcel(Parcel dest, int flags) {
144 dest.writeIntArray(mOps);
145 dest.writeInt(mTransition);
146 dest.writeInt(mTransitionStyle);
147 dest.writeString(mName);
Dianne Hackborndd913a52010-07-22 12:17:04 -0700148 dest.writeInt(mIndex);
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700149 dest.writeInt(mBreadCrumbTitleRes);
150 TextUtils.writeToParcel(mBreadCrumbTitleText, dest, 0);
151 dest.writeInt(mBreadCrumbShortTitleRes);
152 TextUtils.writeToParcel(mBreadCrumbShortTitleText, dest, 0);
George Mountd4c3c912014-06-09 12:31:34 -0700153 dest.writeStringList(mSharedElementSourceNames);
154 dest.writeStringList(mSharedElementTargetNames);
George Mounta0ffaff2017-04-26 13:10:59 -0700155 dest.writeInt(mReorderingAllowed ? 1 : 0);
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700156 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700157
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700158 public static final @android.annotation.NonNull Parcelable.Creator<BackStackState> CREATOR
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700159 = new Parcelable.Creator<BackStackState>() {
160 public BackStackState createFromParcel(Parcel in) {
161 return new BackStackState(in);
162 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700163
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700164 public BackStackState[] newArray(int size) {
165 return new BackStackState[size];
166 }
167 };
168}
169
170/**
171 * @hide Entry of an operation on the fragment back stack.
172 */
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700173final class BackStackRecord extends FragmentTransaction implements
George Mounteca8e222016-07-07 13:13:05 -0700174 FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator {
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700175 static final String TAG = FragmentManagerImpl.TAG;
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700176
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700177 final FragmentManagerImpl mManager;
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700178
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700179 static final int OP_NULL = 0;
180 static final int OP_ADD = 1;
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -0700181 static final int OP_REPLACE = 2;
182 static final int OP_REMOVE = 3;
183 static final int OP_HIDE = 4;
184 static final int OP_SHOW = 5;
Dianne Hackborn47c41562011-04-15 19:00:20 -0700185 static final int OP_DETACH = 6;
186 static final int OP_ATTACH = 7;
Adam Powell5f3a05c2017-01-27 16:51:03 -0800187 static final int OP_SET_PRIMARY_NAV = 8;
188 static final int OP_UNSET_PRIMARY_NAV = 9;
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700189
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700190 static final class Op {
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700191 int cmd;
192 Fragment fragment;
193 int enterAnim;
194 int exitAnim;
Chet Haasebc377842011-03-22 11:35:22 -0700195 int popEnterAnim;
196 int popExitAnim;
Adam Powell5f3a05c2017-01-27 16:51:03 -0800197
198 Op() {
199 }
200
201 Op(int cmd, Fragment fragment) {
202 this.cmd = cmd;
203 this.fragment = fragment;
204 }
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700205 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700206
George Mountf2045f82016-06-27 13:15:01 -0700207 ArrayList<Op> mOps = new ArrayList<>();
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700208 int mEnterAnim;
209 int mExitAnim;
Chet Haasebc377842011-03-22 11:35:22 -0700210 int mPopEnterAnim;
211 int mPopExitAnim;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700212 int mTransition;
213 int mTransitionStyle;
214 boolean mAddToBackStack;
Adam Powell0c24a552010-11-03 16:44:11 -0700215 boolean mAllowAddToBackStack = true;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700216 String mName;
217 boolean mCommitted;
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700218 int mIndex = -1;
George Mounta0ffaff2017-04-26 13:10:59 -0700219 boolean mReorderingAllowed;
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700220
Adam Powelladfd62c2017-01-31 14:54:07 -0800221 ArrayList<Runnable> mCommitRunnables;
222
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700223 int mBreadCrumbTitleRes;
224 CharSequence mBreadCrumbTitleText;
225 int mBreadCrumbShortTitleRes;
226 CharSequence mBreadCrumbShortTitleText;
227
George Mountd4c3c912014-06-09 12:31:34 -0700228 ArrayList<String> mSharedElementSourceNames;
229 ArrayList<String> mSharedElementTargetNames;
230
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700231 @Override
232 public String toString() {
233 StringBuilder sb = new StringBuilder(128);
234 sb.append("BackStackEntry{");
235 sb.append(Integer.toHexString(System.identityHashCode(this)));
236 if (mIndex >= 0) {
237 sb.append(" #");
238 sb.append(mIndex);
239 }
240 if (mName != null) {
241 sb.append(" ");
242 sb.append(mName);
243 }
244 sb.append("}");
245 return sb.toString();
246 }
247
Dianne Hackborn30d71892010-12-11 10:37:55 -0800248 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700249 dump(prefix, writer, true);
250 }
251
252 void dump(String prefix, PrintWriter writer, boolean full) {
253 if (full) {
George Mountd4c3c912014-06-09 12:31:34 -0700254 writer.print(prefix);
255 writer.print("mName=");
256 writer.print(mName);
257 writer.print(" mIndex=");
258 writer.print(mIndex);
259 writer.print(" mCommitted=");
260 writer.println(mCommitted);
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700261 if (mTransition != FragmentTransaction.TRANSIT_NONE) {
George Mountd4c3c912014-06-09 12:31:34 -0700262 writer.print(prefix);
263 writer.print("mTransition=#");
264 writer.print(Integer.toHexString(mTransition));
265 writer.print(" mTransitionStyle=#");
266 writer.println(Integer.toHexString(mTransitionStyle));
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700267 }
George Mountd4c3c912014-06-09 12:31:34 -0700268 if (mEnterAnim != 0 || mExitAnim != 0) {
269 writer.print(prefix);
270 writer.print("mEnterAnim=#");
271 writer.print(Integer.toHexString(mEnterAnim));
272 writer.print(" mExitAnim=#");
273 writer.println(Integer.toHexString(mExitAnim));
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700274 }
George Mountd4c3c912014-06-09 12:31:34 -0700275 if (mPopEnterAnim != 0 || mPopExitAnim != 0) {
276 writer.print(prefix);
277 writer.print("mPopEnterAnim=#");
278 writer.print(Integer.toHexString(mPopEnterAnim));
279 writer.print(" mPopExitAnim=#");
280 writer.println(Integer.toHexString(mPopExitAnim));
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700281 }
282 if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) {
George Mountd4c3c912014-06-09 12:31:34 -0700283 writer.print(prefix);
284 writer.print("mBreadCrumbTitleRes=#");
285 writer.print(Integer.toHexString(mBreadCrumbTitleRes));
286 writer.print(" mBreadCrumbTitleText=");
287 writer.println(mBreadCrumbTitleText);
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700288 }
289 if (mBreadCrumbShortTitleRes != 0 || mBreadCrumbShortTitleText != null) {
George Mountd4c3c912014-06-09 12:31:34 -0700290 writer.print(prefix);
291 writer.print("mBreadCrumbShortTitleRes=#");
292 writer.print(Integer.toHexString(mBreadCrumbShortTitleRes));
293 writer.print(" mBreadCrumbShortTitleText=");
294 writer.println(mBreadCrumbShortTitleText);
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700295 }
Dianne Hackborn30d71892010-12-11 10:37:55 -0800296 }
297
George Mountf2045f82016-06-27 13:15:01 -0700298 if (!mOps.isEmpty()) {
George Mountd4c3c912014-06-09 12:31:34 -0700299 writer.print(prefix);
300 writer.println("Operations:");
Dianne Hackborn30d71892010-12-11 10:37:55 -0800301 String innerPrefix = prefix + " ";
George Mountf2045f82016-06-27 13:15:01 -0700302 final int numOps = mOps.size();
303 for (int opNum = 0; opNum < numOps; opNum++) {
304 final Op op = mOps.get(opNum);
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700305 String cmdStr;
306 switch (op.cmd) {
George Mountd4c3c912014-06-09 12:31:34 -0700307 case OP_NULL:
308 cmdStr = "NULL";
309 break;
310 case OP_ADD:
311 cmdStr = "ADD";
312 break;
313 case OP_REPLACE:
314 cmdStr = "REPLACE";
315 break;
316 case OP_REMOVE:
317 cmdStr = "REMOVE";
318 break;
319 case OP_HIDE:
320 cmdStr = "HIDE";
321 break;
322 case OP_SHOW:
323 cmdStr = "SHOW";
324 break;
325 case OP_DETACH:
326 cmdStr = "DETACH";
327 break;
328 case OP_ATTACH:
329 cmdStr = "ATTACH";
330 break;
Adam Powell5f3a05c2017-01-27 16:51:03 -0800331 case OP_SET_PRIMARY_NAV:
332 cmdStr="SET_PRIMARY_NAV";
333 break;
334 case OP_UNSET_PRIMARY_NAV:
335 cmdStr="UNSET_PRIMARY_NAV";
336 break;
337
George Mountd4c3c912014-06-09 12:31:34 -0700338 default:
339 cmdStr = "cmd=" + op.cmd;
340 break;
Dianne Hackborn30d71892010-12-11 10:37:55 -0800341 }
George Mountd4c3c912014-06-09 12:31:34 -0700342 writer.print(prefix);
343 writer.print(" Op #");
George Mountf2045f82016-06-27 13:15:01 -0700344 writer.print(opNum);
George Mountd4c3c912014-06-09 12:31:34 -0700345 writer.print(": ");
346 writer.print(cmdStr);
347 writer.print(" ");
348 writer.println(op.fragment);
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700349 if (full) {
350 if (op.enterAnim != 0 || op.exitAnim != 0) {
George Mountd4c3c912014-06-09 12:31:34 -0700351 writer.print(innerPrefix);
352 writer.print("enterAnim=#");
353 writer.print(Integer.toHexString(op.enterAnim));
354 writer.print(" exitAnim=#");
355 writer.println(Integer.toHexString(op.exitAnim));
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700356 }
357 if (op.popEnterAnim != 0 || op.popExitAnim != 0) {
George Mountd4c3c912014-06-09 12:31:34 -0700358 writer.print(innerPrefix);
359 writer.print("popEnterAnim=#");
360 writer.print(Integer.toHexString(op.popEnterAnim));
361 writer.print(" popExitAnim=#");
362 writer.println(Integer.toHexString(op.popExitAnim));
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700363 }
Chet Haasebc377842011-03-22 11:35:22 -0700364 }
Dianne Hackborn30d71892010-12-11 10:37:55 -0800365 }
366 }
367 }
368
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700369 public BackStackRecord(FragmentManagerImpl manager) {
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700370 mManager = manager;
George Mounta0ffaff2017-04-26 13:10:59 -0700371 mReorderingAllowed = mManager.getTargetSdk() > Build.VERSION_CODES.N_MR1;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700372 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700373
374 public int getId() {
375 return mIndex;
376 }
377
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800378 public int getBreadCrumbTitleRes() {
379 return mBreadCrumbTitleRes;
380 }
381
382 public int getBreadCrumbShortTitleRes() {
383 return mBreadCrumbShortTitleRes;
384 }
385
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700386 public CharSequence getBreadCrumbTitle() {
George Mountd5f70892016-12-08 13:15:29 -0800387 if (mBreadCrumbTitleRes != 0 && mManager.mHost != null) {
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700388 return mManager.mHost.getContext().getText(mBreadCrumbTitleRes);
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700389 }
390 return mBreadCrumbTitleText;
391 }
392
393 public CharSequence getBreadCrumbShortTitle() {
George Mountd5f70892016-12-08 13:15:29 -0800394 if (mBreadCrumbShortTitleRes != 0 && mManager.mHost != null) {
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700395 return mManager.mHost.getContext().getText(mBreadCrumbShortTitleRes);
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700396 }
397 return mBreadCrumbShortTitleText;
398 }
399
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700400 void addOp(Op op) {
George Mountf2045f82016-06-27 13:15:01 -0700401 mOps.add(op);
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700402 op.enterAnim = mEnterAnim;
403 op.exitAnim = mExitAnim;
Chet Haasebc377842011-03-22 11:35:22 -0700404 op.popEnterAnim = mPopEnterAnim;
405 op.popExitAnim = mPopExitAnim;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700406 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700407
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700408 public FragmentTransaction add(Fragment fragment, String tag) {
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -0700409 doAddOp(0, fragment, tag, OP_ADD);
410 return this;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700411 }
412
413 public FragmentTransaction add(int containerViewId, Fragment fragment) {
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -0700414 doAddOp(containerViewId, fragment, null, OP_ADD);
415 return this;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700416 }
417
418 public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -0700419 doAddOp(containerViewId, fragment, tag, OP_ADD);
420 return this;
421 }
422
423 private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
George Mountf1d88e62017-03-13 10:47:57 -0700424 if (mManager.getTargetSdk() > Build.VERSION_CODES.N_MR1) {
Clara Bayarricd916f22016-06-13 13:14:51 +0100425 final Class fragmentClass = fragment.getClass();
426 final int modifiers = fragmentClass.getModifiers();
George Mountd5f70892016-12-08 13:15:29 -0800427 if ((fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
Clara Bayarricd916f22016-06-13 13:14:51 +0100428 || (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers)))) {
Clara Bayarrieb7b7ec2016-06-23 11:08:55 +0100429 throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName()
430 + " must be a public static class to be properly recreated from"
431 + " instance state.");
Clara Bayarricd916f22016-06-13 13:14:51 +0100432 }
433 }
Dianne Hackborn3e449ce2010-09-11 20:52:31 -0700434 fragment.mFragmentManager = mManager;
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700435
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700436 if (tag != null) {
437 if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
438 throw new IllegalStateException("Can't change tag of fragment "
439 + fragment + ": was " + fragment.mTag
440 + " now " + tag);
441 }
442 fragment.mTag = tag;
443 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700444
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700445 if (containerViewId != 0) {
Adam Powelle01f5952016-02-23 15:25:42 -0800446 if (containerViewId == View.NO_ID) {
447 throw new IllegalArgumentException("Can't add fragment "
448 + fragment + " with tag " + tag + " to container view with no id");
449 }
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700450 if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
451 throw new IllegalStateException("Can't change container ID of fragment "
452 + fragment + ": was " + fragment.mFragmentId
453 + " now " + containerViewId);
454 }
455 fragment.mContainerId = fragment.mFragmentId = containerViewId;
456 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700457
Adam Powell5f3a05c2017-01-27 16:51:03 -0800458 addOp(new Op(opcmd, fragment));
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700459 }
460
461 public FragmentTransaction replace(int containerViewId, Fragment fragment) {
462 return replace(containerViewId, fragment, null);
463 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700464
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700465 public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) {
466 if (containerViewId == 0) {
467 throw new IllegalArgumentException("Must use non-zero containerViewId");
468 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700469
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -0700470 doAddOp(containerViewId, fragment, tag, OP_REPLACE);
471 return this;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700472 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700473
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700474 public FragmentTransaction remove(Fragment fragment) {
Adam Powell5f3a05c2017-01-27 16:51:03 -0800475 addOp(new Op(OP_REMOVE, fragment));
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700476
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700477 return this;
478 }
479
480 public FragmentTransaction hide(Fragment fragment) {
Adam Powell5f3a05c2017-01-27 16:51:03 -0800481 addOp(new Op(OP_HIDE, fragment));
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700482
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700483 return this;
484 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700485
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700486 public FragmentTransaction show(Fragment fragment) {
Adam Powell5f3a05c2017-01-27 16:51:03 -0800487 addOp(new Op(OP_SHOW, fragment));
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700488
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700489 return this;
490 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700491
Dianne Hackborn47c41562011-04-15 19:00:20 -0700492 public FragmentTransaction detach(Fragment fragment) {
Adam Powell5f3a05c2017-01-27 16:51:03 -0800493 addOp(new Op(OP_DETACH, fragment));
Dianne Hackborn47c41562011-04-15 19:00:20 -0700494
495 return this;
496 }
497
498 public FragmentTransaction attach(Fragment fragment) {
Adam Powell5f3a05c2017-01-27 16:51:03 -0800499 addOp(new Op(OP_ATTACH, fragment));
500
501 return this;
502 }
503
504 public FragmentTransaction setPrimaryNavigationFragment(Fragment fragment) {
505 addOp(new Op(OP_SET_PRIMARY_NAV, fragment));
Dianne Hackborn47c41562011-04-15 19:00:20 -0700506
507 return this;
508 }
509
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700510 public FragmentTransaction setCustomAnimations(int enter, int exit) {
Chet Haasebc377842011-03-22 11:35:22 -0700511 return setCustomAnimations(enter, exit, 0, 0);
512 }
513
514 public FragmentTransaction setCustomAnimations(int enter, int exit,
515 int popEnter, int popExit) {
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700516 mEnterAnim = enter;
517 mExitAnim = exit;
Chet Haasebc377842011-03-22 11:35:22 -0700518 mPopEnterAnim = popEnter;
519 mPopExitAnim = popExit;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700520 return this;
521 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700522
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700523 public FragmentTransaction setTransition(int transition) {
524 mTransition = transition;
525 return this;
526 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700527
George Mountd4c3c912014-06-09 12:31:34 -0700528 @Override
George Mount448bace2014-08-18 16:27:43 -0700529 public FragmentTransaction addSharedElement(View sharedElement, String name) {
530 String transitionName = sharedElement.getTransitionName();
531 if (transitionName == null) {
532 throw new IllegalArgumentException("Unique transitionNames are required for all" +
533 " sharedElements");
534 }
535 if (mSharedElementSourceNames == null) {
536 mSharedElementSourceNames = new ArrayList<String>();
537 mSharedElementTargetNames = new ArrayList<String>();
George Mount4efeb4f2016-11-21 16:33:22 -0800538 } else if (mSharedElementTargetNames.contains(name)) {
539 throw new IllegalArgumentException("A shared element with the target name '"
540 + name + "' has already been added to the transaction.");
541 } else if (mSharedElementSourceNames.contains(transitionName)) {
542 throw new IllegalArgumentException("A shared element with the source name '"
543 + transitionName + " has already been added to the transaction.");
George Mount448bace2014-08-18 16:27:43 -0700544 }
545 mSharedElementSourceNames.add(transitionName);
546 mSharedElementTargetNames.add(name);
547 return this;
548 }
549
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700550 public FragmentTransaction setTransitionStyle(int styleRes) {
551 mTransitionStyle = styleRes;
552 return this;
553 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700554
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700555 public FragmentTransaction addToBackStack(String name) {
Adam Powell0c24a552010-11-03 16:44:11 -0700556 if (!mAllowAddToBackStack) {
557 throw new IllegalStateException(
558 "This FragmentTransaction is not allowed to be added to the back stack.");
559 }
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700560 mAddToBackStack = true;
561 mName = name;
562 return this;
563 }
564
Adam Powell0c24a552010-11-03 16:44:11 -0700565 public boolean isAddToBackStackAllowed() {
566 return mAllowAddToBackStack;
567 }
568
569 public FragmentTransaction disallowAddToBackStack() {
570 if (mAddToBackStack) {
571 throw new IllegalStateException(
572 "This transaction is already being added to the back stack");
573 }
574 mAllowAddToBackStack = false;
575 return this;
576 }
577
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700578 public FragmentTransaction setBreadCrumbTitle(int res) {
579 mBreadCrumbTitleRes = res;
580 mBreadCrumbTitleText = null;
581 return this;
582 }
583
584 public FragmentTransaction setBreadCrumbTitle(CharSequence text) {
585 mBreadCrumbTitleRes = 0;
586 mBreadCrumbTitleText = text;
587 return this;
588 }
589
590 public FragmentTransaction setBreadCrumbShortTitle(int res) {
591 mBreadCrumbShortTitleRes = res;
592 mBreadCrumbShortTitleText = null;
593 return this;
594 }
595
596 public FragmentTransaction setBreadCrumbShortTitle(CharSequence text) {
597 mBreadCrumbShortTitleRes = 0;
598 mBreadCrumbShortTitleText = text;
599 return this;
600 }
601
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700602 void bumpBackStackNesting(int amt) {
603 if (!mAddToBackStack) {
604 return;
605 }
George Mountd4c3c912014-06-09 12:31:34 -0700606 if (FragmentManagerImpl.DEBUG) {
607 Log.v(TAG, "Bump nesting in " + this
608 + " by " + amt);
609 }
George Mountf2045f82016-06-27 13:15:01 -0700610 final int numOps = mOps.size();
611 for (int opNum = 0; opNum < numOps; opNum++) {
612 final Op op = mOps.get(opNum);
Dianne Hackbornee76efb2012-06-05 10:27:40 -0700613 if (op.fragment != null) {
614 op.fragment.mBackStackNesting += amt;
George Mountd4c3c912014-06-09 12:31:34 -0700615 if (FragmentManagerImpl.DEBUG) {
616 Log.v(TAG, "Bump nesting of "
617 + op.fragment + " to " + op.fragment.mBackStackNesting);
618 }
Dianne Hackbornee76efb2012-06-05 10:27:40 -0700619 }
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700620 }
621 }
622
Adam Powelladfd62c2017-01-31 14:54:07 -0800623 @Override
Adam Powell10d69ac2017-04-25 15:24:49 -0700624 public FragmentTransaction runOnCommit(Runnable runnable) {
Adam Powelladfd62c2017-01-31 14:54:07 -0800625 if (runnable == null) {
626 throw new IllegalArgumentException("runnable cannot be null");
627 }
628 disallowAddToBackStack();
629 if (mCommitRunnables == null) {
630 mCommitRunnables = new ArrayList<>();
631 }
632 mCommitRunnables.add(runnable);
633 return this;
634 }
635
636 public void runOnCommitRunnables() {
637 if (mCommitRunnables != null) {
638 for (int i = 0, N = mCommitRunnables.size(); i < N; i++) {
639 mCommitRunnables.get(i).run();
640 }
641 mCommitRunnables = null;
642 }
643 }
644
Dianne Hackborndd913a52010-07-22 12:17:04 -0700645 public int commit() {
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700646 return commitInternal(false);
647 }
648
649 public int commitAllowingStateLoss() {
650 return commitInternal(true);
651 }
George Mountd4c3c912014-06-09 12:31:34 -0700652
Adam Powell8585ed62016-02-04 15:38:20 -0800653 @Override
654 public void commitNow() {
655 disallowAddToBackStack();
656 mManager.execSingleAction(this, false);
657 }
658
659 @Override
660 public void commitNowAllowingStateLoss() {
661 disallowAddToBackStack();
662 mManager.execSingleAction(this, true);
663 }
664
George Mounteca8e222016-07-07 13:13:05 -0700665 @Override
George Mounta0ffaff2017-04-26 13:10:59 -0700666 public FragmentTransaction setReorderingAllowed(boolean reorderingAllowed) {
667 mReorderingAllowed = reorderingAllowed;
George Mounteca8e222016-07-07 13:13:05 -0700668 return this;
669 }
670
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700671 int commitInternal(boolean allowStateLoss) {
George Mountd4c3c912014-06-09 12:31:34 -0700672 if (mCommitted) {
673 throw new IllegalStateException("commit already called");
674 }
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700675 if (FragmentManagerImpl.DEBUG) {
676 Log.v(TAG, "Commit: " + this);
677 LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
Dianne Hackborn8c841092013-06-24 13:46:13 -0700678 PrintWriter pw = new FastPrintWriter(logw, false, 1024);
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700679 dump(" ", null, pw, null);
Dianne Hackborn8c841092013-06-24 13:46:13 -0700680 pw.flush();
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700681 }
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700682 mCommitted = true;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700683 if (mAddToBackStack) {
684 mIndex = mManager.allocBackStackIndex(this);
685 } else {
686 mIndex = -1;
687 }
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700688 mManager.enqueueAction(this, allowStateLoss);
Dianne Hackborndd913a52010-07-22 12:17:04 -0700689 return mIndex;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700690 }
George Mountd4c3c912014-06-09 12:31:34 -0700691
George Mounteca8e222016-07-07 13:13:05 -0700692 /**
George Mount86bfc662016-07-12 16:06:06 -0700693 * Implementation of {@link android.app.FragmentManagerImpl.OpGenerator}.
George Mounteca8e222016-07-07 13:13:05 -0700694 * This operation is added to the list of pending actions during {@link #commit()}, and
695 * will be executed on the UI thread to run this FragmentTransaction.
696 *
697 * @param records Modified to add this BackStackRecord
698 * @param isRecordPop Modified to add a false (this isn't a pop)
699 * @return true always because the records and isRecordPop will always be changed
700 */
701 @Override
702 public boolean generateOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
George Mountd4c3c912014-06-09 12:31:34 -0700703 if (FragmentManagerImpl.DEBUG) {
704 Log.v(TAG, "Run: " + this);
705 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700706
George Mounteca8e222016-07-07 13:13:05 -0700707 records.add(this);
708 isRecordPop.add(false);
Dianne Hackborndd913a52010-07-22 12:17:04 -0700709 if (mAddToBackStack) {
George Mounteca8e222016-07-07 13:13:05 -0700710 mManager.addBackStackState(this);
Dianne Hackborndd913a52010-07-22 12:17:04 -0700711 }
George Mounteca8e222016-07-07 13:13:05 -0700712 return true;
713 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700714
George Mount86bfc662016-07-12 16:06:06 -0700715 boolean interactsWith(int containerId) {
716 final int numOps = mOps.size();
717 for (int opNum = 0; opNum < numOps; opNum++) {
718 final Op op = mOps.get(opNum);
Adam Powell5f3a05c2017-01-27 16:51:03 -0800719 final int fragContainer = op.fragment != null ? op.fragment.mContainerId : 0;
720 if (fragContainer != 0 && fragContainer == containerId) {
George Mount86bfc662016-07-12 16:06:06 -0700721 return true;
722 }
723 }
724 return false;
725 }
726
727 boolean interactsWith(ArrayList<BackStackRecord> records, int startIndex, int endIndex) {
728 if (endIndex == startIndex) {
729 return false;
730 }
731 final int numOps = mOps.size();
732 int lastContainer = -1;
733 for (int opNum = 0; opNum < numOps; opNum++) {
734 final Op op = mOps.get(opNum);
Adam Powell5f3a05c2017-01-27 16:51:03 -0800735 final int container = op.fragment != null ? op.fragment.mContainerId : 0;
George Mount86bfc662016-07-12 16:06:06 -0700736 if (container != 0 && container != lastContainer) {
737 lastContainer = container;
738 for (int i = startIndex; i < endIndex; i++) {
739 BackStackRecord record = records.get(i);
740 final int numThoseOps = record.mOps.size();
741 for (int thoseOpIndex = 0; thoseOpIndex < numThoseOps; thoseOpIndex++) {
742 final Op thatOp = record.mOps.get(thoseOpIndex);
Adam Powell5f3a05c2017-01-27 16:51:03 -0800743 final int thatContainer = thatOp.fragment != null
744 ? thatOp.fragment.mContainerId : 0;
745 if (thatContainer == container) {
George Mount86bfc662016-07-12 16:06:06 -0700746 return true;
747 }
748 }
749 }
750 }
751 }
752 return false;
753 }
754
George Mounteca8e222016-07-07 13:13:05 -0700755 /**
756 * Executes the operations contained within this transaction. The Fragment states will only
757 * be modified if optimizations are not allowed.
758 */
759 void executeOps() {
George Mountf2045f82016-06-27 13:15:01 -0700760 final int numOps = mOps.size();
761 for (int opNum = 0; opNum < numOps; opNum++) {
762 final Op op = mOps.get(opNum);
George Mounteca8e222016-07-07 13:13:05 -0700763 final Fragment f = op.fragment;
Adam Powell5f3a05c2017-01-27 16:51:03 -0800764 if (f != null) {
765 f.setNextTransition(mTransition, mTransitionStyle);
766 }
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700767 switch (op.cmd) {
George Mountf2045f82016-06-27 13:15:01 -0700768 case OP_ADD:
George Mount86bfc662016-07-12 16:06:06 -0700769 f.setNextAnim(op.enterAnim);
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700770 mManager.addFragment(f, false);
George Mountf2045f82016-06-27 13:15:01 -0700771 break;
772 case OP_REMOVE:
George Mount86bfc662016-07-12 16:06:06 -0700773 f.setNextAnim(op.exitAnim);
George Mounteca8e222016-07-07 13:13:05 -0700774 mManager.removeFragment(f);
George Mountf2045f82016-06-27 13:15:01 -0700775 break;
776 case OP_HIDE:
George Mount86bfc662016-07-12 16:06:06 -0700777 f.setNextAnim(op.exitAnim);
George Mounteca8e222016-07-07 13:13:05 -0700778 mManager.hideFragment(f);
George Mountf2045f82016-06-27 13:15:01 -0700779 break;
780 case OP_SHOW:
George Mount86bfc662016-07-12 16:06:06 -0700781 f.setNextAnim(op.enterAnim);
George Mounteca8e222016-07-07 13:13:05 -0700782 mManager.showFragment(f);
George Mountf2045f82016-06-27 13:15:01 -0700783 break;
784 case OP_DETACH:
George Mount86bfc662016-07-12 16:06:06 -0700785 f.setNextAnim(op.exitAnim);
George Mounteca8e222016-07-07 13:13:05 -0700786 mManager.detachFragment(f);
George Mountf2045f82016-06-27 13:15:01 -0700787 break;
788 case OP_ATTACH:
George Mount86bfc662016-07-12 16:06:06 -0700789 f.setNextAnim(op.enterAnim);
George Mounteca8e222016-07-07 13:13:05 -0700790 mManager.attachFragment(f);
George Mountf2045f82016-06-27 13:15:01 -0700791 break;
Adam Powell5f3a05c2017-01-27 16:51:03 -0800792 case OP_SET_PRIMARY_NAV:
793 mManager.setPrimaryNavigationFragment(f);
794 break;
795 case OP_UNSET_PRIMARY_NAV:
796 mManager.setPrimaryNavigationFragment(null);
797 break;
George Mountf2045f82016-06-27 13:15:01 -0700798 default:
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700799 throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700800 }
George Mounta0ffaff2017-04-26 13:10:59 -0700801 if (!mReorderingAllowed && op.cmd != OP_ADD && f != null) {
George Mounteca8e222016-07-07 13:13:05 -0700802 mManager.moveFragmentToExpectedState(f);
803 }
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700804 }
George Mounta0ffaff2017-04-26 13:10:59 -0700805 if (!mReorderingAllowed) {
George Mounteca8e222016-07-07 13:13:05 -0700806 // Added fragments are added at the end to comply with prior behavior.
George Mount687e5502016-11-02 14:33:18 -0700807 mManager.moveToState(mManager.mCurState, true);
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700808 }
809 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700810
George Mounteca8e222016-07-07 13:13:05 -0700811 /**
812 * Reverses the execution of the operations within this transaction. The Fragment states will
813 * only be modified if optimizations are not allowed.
George Mounta42f8e42017-02-08 10:52:02 -0800814 *
815 * @param moveToState {@code true} if added fragments should be moved to their final state
816 * in unoptimized transactions
George Mounteca8e222016-07-07 13:13:05 -0700817 */
George Mounta42f8e42017-02-08 10:52:02 -0800818 void executePopOps(boolean moveToState) {
George Mounteca8e222016-07-07 13:13:05 -0700819 for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
George Mountf2045f82016-06-27 13:15:01 -0700820 final Op op = mOps.get(opNum);
George Mounteca8e222016-07-07 13:13:05 -0700821 Fragment f = op.fragment;
Adam Powell5f3a05c2017-01-27 16:51:03 -0800822 if (f != null) {
823 f.setNextTransition(FragmentManagerImpl.reverseTransit(mTransition),
824 mTransitionStyle);
825 }
George Mounteca8e222016-07-07 13:13:05 -0700826 switch (op.cmd) {
827 case OP_ADD:
George Mount86bfc662016-07-12 16:06:06 -0700828 f.setNextAnim(op.popExitAnim);
George Mounteca8e222016-07-07 13:13:05 -0700829 mManager.removeFragment(f);
830 break;
831 case OP_REMOVE:
George Mount86bfc662016-07-12 16:06:06 -0700832 f.setNextAnim(op.popEnterAnim);
George Mounteca8e222016-07-07 13:13:05 -0700833 mManager.addFragment(f, false);
834 break;
835 case OP_HIDE:
George Mount86bfc662016-07-12 16:06:06 -0700836 f.setNextAnim(op.popEnterAnim);
George Mounteca8e222016-07-07 13:13:05 -0700837 mManager.showFragment(f);
838 break;
839 case OP_SHOW:
George Mount86bfc662016-07-12 16:06:06 -0700840 f.setNextAnim(op.popExitAnim);
George Mounteca8e222016-07-07 13:13:05 -0700841 mManager.hideFragment(f);
842 break;
843 case OP_DETACH:
George Mount86bfc662016-07-12 16:06:06 -0700844 f.setNextAnim(op.popEnterAnim);
George Mounteca8e222016-07-07 13:13:05 -0700845 mManager.attachFragment(f);
846 break;
847 case OP_ATTACH:
George Mount86bfc662016-07-12 16:06:06 -0700848 f.setNextAnim(op.popExitAnim);
George Mounteca8e222016-07-07 13:13:05 -0700849 mManager.detachFragment(f);
850 break;
Adam Powell5f3a05c2017-01-27 16:51:03 -0800851 case OP_SET_PRIMARY_NAV:
852 mManager.setPrimaryNavigationFragment(null);
853 break;
854 case OP_UNSET_PRIMARY_NAV:
855 mManager.setPrimaryNavigationFragment(f);
856 break;
George Mounteca8e222016-07-07 13:13:05 -0700857 default:
858 throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
859 }
George Mounta0ffaff2017-04-26 13:10:59 -0700860 if (!mReorderingAllowed && op.cmd != OP_REMOVE && f != null) {
George Mounteca8e222016-07-07 13:13:05 -0700861 mManager.moveFragmentToExpectedState(f);
George Mountf2045f82016-06-27 13:15:01 -0700862 }
863 }
George Mounta0ffaff2017-04-26 13:10:59 -0700864 if (!mReorderingAllowed && moveToState) {
George Mount687e5502016-11-02 14:33:18 -0700865 mManager.moveToState(mManager.mCurState, true);
George Mountf2045f82016-06-27 13:15:01 -0700866 }
George Mounteca8e222016-07-07 13:13:05 -0700867 }
George Mountf2045f82016-06-27 13:15:01 -0700868
George Mounteca8e222016-07-07 13:13:05 -0700869 /**
Adam Powell5f3a05c2017-01-27 16:51:03 -0800870 * Expands all meta-ops into their more primitive equivalents. This must be called prior to
871 * {@link #executeOps()} or any other call that operations on mOps for forward navigation.
872 * It should not be called for pop/reverse navigation operations.
873 *
874 * <p>Removes all OP_REPLACE ops and replaces them with the proper add and remove
875 * operations that are equivalent to the replace.</p>
876 *
877 * <p>Adds OP_UNSET_PRIMARY_NAV ops to match OP_SET_PRIMARY_NAV, OP_REMOVE and OP_DETACH
878 * ops so that we can restore the old primary nav fragment later. Since callers call this
879 * method in a loop before running ops from several transactions at once, the caller should
880 * pass the return value from this method as the oldPrimaryNav parameter for the next call.
881 * The first call in such a loop should pass the value of
882 * {@link FragmentManager#getPrimaryNavigationFragment()}.</p>
George Mounteca8e222016-07-07 13:13:05 -0700883 *
884 * @param added Initialized to the fragments that are in the mManager.mAdded, this
885 * will be modified to contain the fragments that will be in mAdded
886 * after the execution ({@link #executeOps()}.
Adam Powell5f3a05c2017-01-27 16:51:03 -0800887 * @param oldPrimaryNav The tracked primary navigation fragment as of the beginning of
888 * this set of ops
889 * @return the new oldPrimaryNav fragment after this record's ops would be run
George Mounteca8e222016-07-07 13:13:05 -0700890 */
Aurimas Liutikas221f15d42017-03-30 16:32:58 -0700891 @SuppressWarnings("ReferenceEquality")
Adam Powell5f3a05c2017-01-27 16:51:03 -0800892 Fragment expandOps(ArrayList<Fragment> added, Fragment oldPrimaryNav) {
George Mountf2045f82016-06-27 13:15:01 -0700893 for (int opNum = 0; opNum < mOps.size(); opNum++) {
894 final Op op = mOps.get(opNum);
895 switch (op.cmd) {
896 case OP_ADD:
897 case OP_ATTACH:
898 added.add(op.fragment);
George Mount86bfc662016-07-12 16:06:06 -0700899 break;
George Mountf2045f82016-06-27 13:15:01 -0700900 case OP_REMOVE:
Adam Powell5f3a05c2017-01-27 16:51:03 -0800901 case OP_DETACH: {
George Mountf2045f82016-06-27 13:15:01 -0700902 added.remove(op.fragment);
Adam Powell5f3a05c2017-01-27 16:51:03 -0800903 if (op.fragment == oldPrimaryNav) {
904 mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, op.fragment));
905 opNum++;
906 oldPrimaryNav = null;
907 }
908 }
909 break;
George Mountf2045f82016-06-27 13:15:01 -0700910 case OP_REPLACE: {
Adam Powell5f3a05c2017-01-27 16:51:03 -0800911 final Fragment f = op.fragment;
912 final int containerId = f.mContainerId;
George Mountf2045f82016-06-27 13:15:01 -0700913 boolean alreadyAdded = false;
914 for (int i = added.size() - 1; i >= 0; i--) {
Adam Powell5f3a05c2017-01-27 16:51:03 -0800915 final Fragment old = added.get(i);
George Mountf2045f82016-06-27 13:15:01 -0700916 if (old.mContainerId == containerId) {
917 if (old == f) {
918 alreadyAdded = true;
919 } else {
Adam Powell5f3a05c2017-01-27 16:51:03 -0800920 // This is duplicated from above since we only make
921 // a single pass for expanding ops. Unset any outgoing primary nav.
922 if (old == oldPrimaryNav) {
923 mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, old));
924 opNum++;
925 oldPrimaryNav = null;
926 }
927 final Op removeOp = new Op(OP_REMOVE, old);
George Mountf2045f82016-06-27 13:15:01 -0700928 removeOp.enterAnim = op.enterAnim;
929 removeOp.popEnterAnim = op.popEnterAnim;
930 removeOp.exitAnim = op.exitAnim;
931 removeOp.popExitAnim = op.popExitAnim;
932 mOps.add(opNum, removeOp);
933 added.remove(old);
934 opNum++;
935 }
936 }
937 }
938 if (alreadyAdded) {
939 mOps.remove(opNum);
940 opNum--;
941 } else {
942 op.cmd = OP_ADD;
943 added.add(f);
944 }
945 }
946 break;
Adam Powell5f3a05c2017-01-27 16:51:03 -0800947 case OP_SET_PRIMARY_NAV: {
948 // It's ok if this is null, that means we will restore to no active
949 // primary navigation fragment on a pop.
950 mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, oldPrimaryNav));
951 opNum++;
952 // Will be set by the OP_SET_PRIMARY_NAV we inserted before when run
953 oldPrimaryNav = op.fragment;
954 }
955 break;
George Mountf2045f82016-06-27 13:15:01 -0700956 }
957 }
Adam Powell5f3a05c2017-01-27 16:51:03 -0800958 return oldPrimaryNav;
George Mountf2045f82016-06-27 13:15:01 -0700959 }
960
George Mount99c532d2017-01-11 10:23:40 -0800961 /**
962 * Removes fragments that are added or removed during a pop operation.
963 *
964 * @param added Initialized to the fragments that are in the mManager.mAdded, this
965 * will be modified to contain the fragments that will be in mAdded
966 * after the execution ({@link #executeOps()}.
967 */
968 void trackAddedFragmentsInPop(ArrayList<Fragment> added) {
969 for (int opNum = 0; opNum < mOps.size(); opNum++) {
970 final Op op = mOps.get(opNum);
971 switch (op.cmd) {
972 case OP_ADD:
973 case OP_ATTACH:
974 added.remove(op.fragment);
975 break;
976 case OP_REMOVE:
977 case OP_DETACH:
978 added.add(op.fragment);
979 break;
980 }
981 }
982 }
983
George Mount86bfc662016-07-12 16:06:06 -0700984 boolean isPostponed() {
985 for (int opNum = 0; opNum < mOps.size(); opNum++) {
George Mountf2045f82016-06-27 13:15:01 -0700986 final Op op = mOps.get(opNum);
George Mount86bfc662016-07-12 16:06:06 -0700987 if (isFragmentPostponed(op)) {
George Mountc855f7d2015-06-10 15:00:17 -0700988 return true;
989 }
990 }
991 return false;
992 }
993
George Mount86bfc662016-07-12 16:06:06 -0700994 void setOnStartPostponedListener(Fragment.OnStartEnterTransitionListener listener) {
995 for (int opNum = 0; opNum < mOps.size(); opNum++) {
996 final Op op = mOps.get(opNum);
997 if (isFragmentPostponed(op)) {
998 op.fragment.setOnStartEnterTransitionListener(listener);
George Mount61f83312015-09-09 16:10:29 -0700999 }
1000 }
1001 }
1002
George Mount86bfc662016-07-12 16:06:06 -07001003 private static boolean isFragmentPostponed(Op op) {
1004 final Fragment fragment = op.fragment;
Adam Powell5f3a05c2017-01-27 16:51:03 -08001005 return fragment != null && fragment.mAdded && fragment.mView != null && !fragment.mDetached
1006 && !fragment.mHidden && fragment.isPostponed();
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001007 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001008
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001009 public String getName() {
1010 return mName;
1011 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001012
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001013 public int getTransition() {
1014 return mTransition;
1015 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001016
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001017 public int getTransitionStyle() {
1018 return mTransitionStyle;
1019 }
Adam Powell2b6230e2010-09-07 17:55:25 -07001020
1021 public boolean isEmpty() {
George Mountf2045f82016-06-27 13:15:01 -07001022 return mOps.isEmpty();
Adam Powell2b6230e2010-09-07 17:55:25 -07001023 }
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001024}