我刚刚创建了一个演示来理解FragmentTransaction的替换方法,但我没有按照Developer Guide获得结果。
活动和片段
public class MainActivity extends AppCompatActivity {
private int count;
private Fragment prevFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button button = (Button) findViewById(R.id.activity_main_bv_add);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
count++;
final FragmentTransaction transaction = getFragmentManager().beginTransaction();
final TestFragment fragment = new TestFragment(count);
if (count == 1) {
transaction.add(R.id.activity_main_rl_container, fragment, fragment.getClass().getSimpleName());
} else if (count == 5) {
transaction.replace(R.id.activity_main_rl_container, fragment, fragment.getClass().getSimpleName());
transaction.addToBackStack(null);
if (prevFragment != null) {
transaction.hide(prevFragment);
}
} else {
transaction.add(R.id.activity_main_rl_container, fragment, fragment.getClass().getSimpleName());
transaction.addToBackStack(null);
if (prevFragment != null) {
transaction.hide(prevFragment);
}
}
prevFragment = fragment;
transaction.commit();
}
});
}
public class TestFragment extends Fragment {
private final String TAG = this.getClass().getSimpleName();
private int number;
public TestFragment(final int number) {
this.number = number;
}
public TestFragment() {
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.e(TAG, "onCreateView : " + number);
final View view = inflater.inflate(R.layout.row_button, null);
final Button button = (Button) view.findViewById(R.id.button);
button.setText("" + number);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.e(TAG, "onDestroyView : " + number);
}
}
}
片段xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
android:orientation="vertical">
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:focusable="false"
android:focusableInTouchMode="false"
/>
</LinearLayout>
活动xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/activity_currency_select"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants"
>
<Button
android:id="@+id/activity_main_bv_add"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="Add More"/>
<RelativeLayout
android:id="@+id/activity_main_rl_container"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_below="@id/activity_main_bv_add"
android:layout_marginTop="20dp"
android:background="@color/colorAccent"></RelativeLayout>
</RelativeLayout>
FragmentTransaction替换方法: 根据Android文档, 替换添加到容器的现有片段。这与使用相同的containerViewId添加的所有当前添加的片段调用remove(Fragment),然后使用此处给出的相同参数添加(int,Fragment,String)基本相同。
假设案例1 :使用replace方法将删除当前(最后和最新)片段并在容器视图中添加新片段。
假设案例2 :使用replace方法将删除添加到同一容器视图中的片段。
但按照上述代码,上述情况似乎没有。
按照显示的代码点击按钮。 在每个按钮上单击直到count == 4,Fragment的新对象将被添加到容器中。
当我们点击按钮时,对于count == 5,这里使用replace方法,当时Fragment的新对象将被添加到容器中,onDestroyView方法被调用为第一个和第三个添加的片段
问题1:如果替换将删除在同一容器中添加的所有片段,那么为什么没有为第二个和第四个添加的片段调用onDestroyView?
问题2:如果替换方法删除了同一容器中的最后添加的片段,那么为什么它不会破坏第4个片段而是第1个和第3个片段?
根据我的理解,行为不符合Developer site上显示的文件。
如果我错了,请纠正我。
答案 0 :(得分:2)
这似乎是replace
方法的错误。
请注意,FragmentManager
的支持版本不会发生这种情况。
第一个标记为过时,第二个标记为已分配,但两者似乎都非常相关。
两者都突出显示,在for
循环中删除片段(来自ArrayList),然后片段的ArrayList在此for
循环内改变其大小,这会导致跳过一些索引,然后删除一些(不是全部)碎片。
这是链接中引用的for循环:
for (int i = 0; i < mManager.mAdded.size(); i++) {
Fragment old = mManager.mAdded.get(i);
// ...
if (f == null || old.mContainerId == f.mContainerId) {
if (old == f) {
op.fragment = f = null;
} else {
if (op.removed == null) {
op.removed = new ArrayList<Fragment>();
}
op.removed.add(old);
old.mNextAnim = op.exitAnim;
if (mAddToBackStack) {
old.mBackStackNesting += 1;
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "Bump nesting of "
+ old + " to " + old.mBackStackNesting);
}
}
mManager.removeFragment(old, mTransition, mTransitionStyle);
}
}
}
在您的具体情况下,您将添加片段1,2,3,4。之后,当您想要用第五个片段替换所有这四个片段时,执行上面的for循环。所以你删除了1st(对应于for循环中的i = 0),片段的arraylist变为2,3,4。然后你选择for循环中的下一个索引(i = 1),但同时arraylist改变了,所以取片段3(对应于i = 1)并删除它。最后,这个arraylist变为2,4和i = 2,并且没有片段对应于索引2.
我希望我能帮助你理解,即使我不拿50分:)
答案 1 :(得分:0)
for (int i=0; i<mManager.mAdded.size(); i++) {
Fragment old = mManager.mAdded.get(i);
if (f ==null ||old.mContainerId == f.mContainerId) {
mManager.removeFragment(old,mTransition, mTransitionStyle);
}
}
MManager.mAdded是一个ArrayList列表,在遍历mManager.removeFragment方法时调用,该方法调用ArrayList remove方法;
Public void removeFragment (Fragmentfragment, int transition, inttransitionStyle) {
MAdded.remove (fragment);
}
这意味着在使用for循环
循环ArrayList列表时使用remove