我遇到的问题是,替换通过XML添加的初始片段不会调用任何破坏生命周期的回调,例如onDetach()
,onDestroy()
,onDestroyView()
,onStop()
等。这是一个问题,因为我想在onDetach()
中执行操作。
这是我的设置。正如谷歌开发者文档所说的那样(https://developer.android.com/guide/components/fragments.html),我创建了一个带有片段的布局,activity_main.xml。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/sky_2"
tools:context=".activity.MainActivity"
tools:ignore="UselessParent,contentDescription">
<fragment
android:id="@+id/frag_container"
android:name="com.example.GameFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<include layout="@layout/footer" />
</RelativeLayout>
我的MainActivity中引用了此布局。作为FYI,包含的页脚只是四个表示选项卡的ImageView。
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!Utils.checkIfNull(findViewById(R.id.frag_container))) {
// if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (!Utils.checkIfNull(savedInstanceState)) {
return;
}
}
// initialize views
initializeViews();
}
当我的应用启动时,它会按预期启动我的GameFragment
。文件说明
当系统创建此活动布局时,它会实例化每个活动布局 在布局中指定的片段并调用onCreateView()方法 对于每一个,检索每个片段的布局。系统插入 片段返回的视图直接代替 元件。
我的GameFragment onCreateView()
回调确实被调用,所有内容都被初始化,我能够执行所有功能。当我更改标签时会出现问题。我通过用新的片段替换当前片段来更改标签。这是我正在使用的功能。
public void addFragmentReplace(int containerId, @NonNull Fragment fragment) {
// check if the fragment has been added already
Fragment temp = mFragmentManager.findFragmentByTag(fragment.getClass().getSimpleName());
if (!Utils.checkIfNull(temp) && temp.isAdded()) {
return;
}
// replace fragment and transition with animation
try {
if (!Utils.isStringEmpty(getTopFragment().getTag()) && getTopFragment().isAdded()) {
// pop back stack
popBackStack();
}
mFragmentManager.beginTransaction().replace(containerId, fragment,
fragment.getClass().getSimpleName()).addToBackStack(null).commit();
} catch (IllegalStateException e) {
e.printStackTrace();
mFragmentManager.beginTransaction().replace(containerId, fragment,
fragment.getClass().getSimpleName()).addToBackStack(null)
.commitAllowingStateLoss(); // used as last resort
}
}
我通过简单地说
来调用该函数addFragmentReplace(R.id.frag_container, new NewsFragment());
我注意到的行为是,当从初始选项卡更改为任何其他选项卡时,我没有收到任何回调。一旦我返回到初始选项卡并更改为任何其他选项卡,一切都很完美。我试着监控我的backstackcount以进一步了解可能发生的事情。在我的MainActivity onCreate()
方法中,我记录了backstackcount,它出现为0,即使我在第一次启动我的应用程序后可以清楚地看到GameFragment。当我更改标签时,我的backstackcount变为1,无论我因addFragmentReplace()
方法更改标签多少次,它都保持为1。我不确定当通过XML添加片段时会发生什么,但我认为这样做或者我的替换功能不正确。提前谢谢!
答案 0 :(得分:0)
我了解到如果您通过XML添加片段,则无法动态删除/替换。我通过编程方式完成所有事情来解决我的问题首先,在MainActivity中添加GameFragment
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (!Utils.checkIfNull(findViewById(R.id.frag_container))) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (!Utils.checkIfNull(savedInstanceState)) {
return;
}
addFragment(R.id.frag_container, new GameFragment());
}
// initialize views
initializeViews();
}
然后我将XML更改为具有FrameLayout容器,而不是片段1。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/sky_2"
tools:context=".activity.MainActivity"
tools:ignore="UselessParent,contentDescription">
<FrameLayout
android:id="@+id/frag_container"
android:name="com.example.GameFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<include layout="@layout/footer" />
</RelativeLayout>