1 问题
1.1 不建议手动管理Fragment
例如当忘记在onPause中移除时fragment时,因旋转屏幕或其它情况重新创建Activity时会导致Fragment被重复添加,屏幕出现错乱.
@Override
protected void onResume() {
super.onResume();
fragment1 = FragmentTrees.newInstance();
getSupportFragmentManager().beginTransaction()
.add(R.id.fragmentContainerView, fragment1)
.commit();
}
1.2 Fragment被重复添加,屏幕出现错乱
第一反应是不是RecyclerView没有设置正确,一顿操作猛如虎之后…
1.3 手动管理正确的方法
当Fragment比较多时容易错漏.
@Override
protected void onResume() {
super.onResume();
fragment1 = FragmentTrees.newInstance();
getSupportFragmentManager().beginTransaction()
.add(R.id.fragmentContainerView, fragment1)
.commit();
}
@Override
protected void onPause() {
getSupportFragmentManager().beginTransaction()
.remove(fragment1)
.commit();
super.onPause();
}
2 避坑指南
使用navigation管理Fragment.
2.1 Activity Layout文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
2.1.1 传递动态参数值
当您要传递动态参数值给Fragment时,在Layout文件中不要设置"app:navGraph"属性,改在Activity onCreate方法中传递动态值参数,如下:
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
NavController navController = navHostFragment.getNavController();
Bundle bundle = new Bundle();
bundle.putString(key,val);
navController.setGraph(R.navigation.nav_trees_of_block,bundle);
navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/trees_of_block"
app:startDestination="@id/fragmentTrees">
<fragment
android:id="@+id/fragmentTrees"
android:name="cn.kuncb.nutswork.activity.self.FragmentTrees"
android:label="@string/view_tree_ok"
tools:layout="@layout/fragment_trees" />
</navigation>
2.1.2 无参数或固定的参数值时
在Layout文件中设置 "app:navGraph"属性,同时navigation文件中写参数
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_trees_of_block" />
</androidx.constraintlayout.widget.ConstraintLayout>
navigation.xml中传递固定值参数,没有参数则把argument节点删除
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/trees_of_block"
app:startDestination="@id/fragmentTrees">
<fragment
android:id="@+id/fragmentTrees"
android:name="cn.kuncb.nutswork.activity.self.FragmentTrees"
android:label="@string/view_tree_ok"
tools:layout="@layout/fragment_trees">
<argument
android:name="KEY"
app:argType="string"
android:defaultValue="kmcb" />
</fragment>
</navigation>
3 总结
- 使用navigation,navigation会自动管理fragment,您只要向navigation.xml添加fragment即可,避免使用代码容易出现的错漏;
- 当要传递动态参数值时,在代码调用setGraph,注意setGraph的参数是传递给navigation.xml文件中app:startDestination这个Fragment;
- 要切换Fragment时,使用下面的代码切换.
3.1 Activity中切换
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
NavController navController = navHostFragment.getNavController();
Bundle bundle = new Bundle();
bundle.putString(key,val);
/**
* 注意
* R.id.fragmentTrees是在navigation.xml中定义的fragment id
* bundle此时传递给R.id.fragmentTrees
*/
navController.navigate(R.id.fragmentTrees,bundle);
3.1 Fragment中切换
NavController navController = Navigation.findNavController(requireActivity(), R.id.fragmentContainerView);
navController.navigate(R.id.Fragment, null);