重新创建 activity 后片段重叠
fragments overlaps after activity is recreated
在我的示例中,我尝试了解片段的 commitAllowingStateLoss()
和 commit()
方法之间的区别。现在我知道如果在 activity 保存实例后使用 commit()
会出现 IllegalArgumentException
(例如,当 activity 在后台时执行 commit()
)。
但是又出现了一个问题,片段重叠。不知道为什么,无法解决问题
我的代码如下。
在FragmentMainActivity中有两个切换片段的按钮。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_fragment1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="fragment 1" />
<Button
android:id="@+id/btn_fragment2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="fragment 2" />
</LinearLayout>
<FrameLayout
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffffff"></FrameLayout>
id为"root"的framelayout是片段的容器。
public class FragmentMainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_main);
findViewById(R.id.btn_fragment1).setOnClickListener(this);
findViewById(R.id.btn_fragment2).setOnClickListener(this);
}
PlusOneFragment plusOneFragment;
PlusTwoFragment plusTwoFragment;
@Override
public void onClick(View v) {
int i = v.getId();
if (i == R.id.btn_fragment1) {
findViewById(R.id.root).postDelayed(new Runnable() {
@Override
public void run() {
final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (getSupportFragmentManager().findFragmentByTag("tag1") == null) {
plusOneFragment = PlusOneFragment.newInstance("1", "2");
transaction.add(R.id.root, plusOneFragment, "tag1");
} else {
plusOneFragment = (PlusOneFragment) getSupportFragmentManager().findFragmentByTag("tag1");
}
if (getSupportFragmentManager().findFragmentByTag("tag2") != null) {
plusTwoFragment = (PlusTwoFragment) getSupportFragmentManager().findFragmentByTag("tag2");
transaction.hide(plusTwoFragment);
}
transaction.show(plusOneFragment).commitAllowingStateLoss();
}
}, 3000);
} else if (i == R.id.btn_fragment2) {
findViewById(R.id.root).postDelayed(new Runnable() {
@Override
public void run() {
final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (getSupportFragmentManager().findFragmentByTag("tag2") == null) {
plusTwoFragment = PlusTwoFragment.newInstance("1", "2");
transaction.add(R.id.root, plusTwoFragment, "tag2");
} else {
plusTwoFragment = (PlusTwoFragment) getSupportFragmentManager().findFragmentByTag("tag2");
}
if (getSupportFragmentManager().findFragmentByTag("tag1") != null) {
plusOneFragment = (PlusOneFragment) getSupportFragmentManager().findFragmentByTag("tag1");
transaction.hide(plusOneFragment);
}
transaction.show(plusTwoFragment).commitAllowingStateLoss();
}
}, 3000);
}
}
}
首先我点击button1显示fragment1,然后点击button2显示fragment2,效果很好。在这些操作之后,我再次单击 button1,然后单击主页,因此该应用程序在后台 运行。为了模拟低内存场景,我然后终止了这个过程。所有这些操作都在 3 秒内完成。
最后,我从最近的记录(activity重新创建)中打开应用程序,发现两个片段相互重叠。这是怎么发生的?(为什么当进程在前台时问题没有发生?)我该怎么处理这个问题?
由于片段保留在后台堆栈中,您必须在打开第二个片段时从后台堆栈中删除第一个片段。使用 popBackStack 可能会解决您的问题
Fragment fragment = (Fragment) YourClass.newInstance();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.flContent, fragment);
//TODO Add to backstack
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
希望对您有所帮助
给你的片段根元素一个背景颜色(比如白色)android:background="@android:color/white"
并再次检查。
这是因为你的片段没有被删除并添加了一个 another.Also 尝试替换方法而不是 add.For 例如:-
fragmentTransaction.replace("containerId", fragment);
因为这会替换 layout.You 中的前一个片段,也可以使用
手动删除您的片段
Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);
if(fragment != null)
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
在我的示例中,我尝试了解片段的 commitAllowingStateLoss()
和 commit()
方法之间的区别。现在我知道如果在 activity 保存实例后使用 commit()
会出现 IllegalArgumentException
(例如,当 activity 在后台时执行 commit()
)。
但是又出现了一个问题,片段重叠。不知道为什么,无法解决问题
我的代码如下。
在FragmentMainActivity中有两个切换片段的按钮。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_fragment1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="fragment 1" />
<Button
android:id="@+id/btn_fragment2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="fragment 2" />
</LinearLayout>
<FrameLayout
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffffff"></FrameLayout>
id为"root"的framelayout是片段的容器。
public class FragmentMainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_main);
findViewById(R.id.btn_fragment1).setOnClickListener(this);
findViewById(R.id.btn_fragment2).setOnClickListener(this);
}
PlusOneFragment plusOneFragment;
PlusTwoFragment plusTwoFragment;
@Override
public void onClick(View v) {
int i = v.getId();
if (i == R.id.btn_fragment1) {
findViewById(R.id.root).postDelayed(new Runnable() {
@Override
public void run() {
final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (getSupportFragmentManager().findFragmentByTag("tag1") == null) {
plusOneFragment = PlusOneFragment.newInstance("1", "2");
transaction.add(R.id.root, plusOneFragment, "tag1");
} else {
plusOneFragment = (PlusOneFragment) getSupportFragmentManager().findFragmentByTag("tag1");
}
if (getSupportFragmentManager().findFragmentByTag("tag2") != null) {
plusTwoFragment = (PlusTwoFragment) getSupportFragmentManager().findFragmentByTag("tag2");
transaction.hide(plusTwoFragment);
}
transaction.show(plusOneFragment).commitAllowingStateLoss();
}
}, 3000);
} else if (i == R.id.btn_fragment2) {
findViewById(R.id.root).postDelayed(new Runnable() {
@Override
public void run() {
final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (getSupportFragmentManager().findFragmentByTag("tag2") == null) {
plusTwoFragment = PlusTwoFragment.newInstance("1", "2");
transaction.add(R.id.root, plusTwoFragment, "tag2");
} else {
plusTwoFragment = (PlusTwoFragment) getSupportFragmentManager().findFragmentByTag("tag2");
}
if (getSupportFragmentManager().findFragmentByTag("tag1") != null) {
plusOneFragment = (PlusOneFragment) getSupportFragmentManager().findFragmentByTag("tag1");
transaction.hide(plusOneFragment);
}
transaction.show(plusTwoFragment).commitAllowingStateLoss();
}
}, 3000);
}
}
}
首先我点击button1显示fragment1,然后点击button2显示fragment2,效果很好。在这些操作之后,我再次单击 button1,然后单击主页,因此该应用程序在后台 运行。为了模拟低内存场景,我然后终止了这个过程。所有这些操作都在 3 秒内完成。
最后,我从最近的记录(activity重新创建)中打开应用程序,发现两个片段相互重叠。这是怎么发生的?(为什么当进程在前台时问题没有发生?)我该怎么处理这个问题?
由于片段保留在后台堆栈中,您必须在打开第二个片段时从后台堆栈中删除第一个片段。使用 popBackStack 可能会解决您的问题
Fragment fragment = (Fragment) YourClass.newInstance();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.flContent, fragment);
//TODO Add to backstack
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
希望对您有所帮助
给你的片段根元素一个背景颜色(比如白色)android:background="@android:color/white"
并再次检查。
这是因为你的片段没有被删除并添加了一个 another.Also 尝试替换方法而不是 add.For 例如:-
fragmentTransaction.replace("containerId", fragment);
因为这会替换 layout.You 中的前一个片段,也可以使用
手动删除您的片段Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);
if(fragment != null)
getSupportFragmentManager().beginTransaction().remove(fragment).commit();