Android Studio 3.5 NavigationUIを使用してFragmentをリロードする
タイトルは短すぎて意味が正確ではないかも。
「NavigationUIを使用している場合に、メニューから遷移可能な宛先画面(Destination)をリロードする。」 もし、NavigationUIを使っていないなら、NavController#navigateで遷移すればいいです。
経緯
Android Studio3.5のナビゲーションドロワーアクティビティをベースにActivityを作っているときに、ユーザ操作によって設定を書き換え、それを反映するために画面をリロードしたかった。
だが、NavController#navigateで遷移すると画面(Fragment)のonSaveInstanceStateでViewModelがヌルポになる。ViewModelインスタンスがfinalizeされた?
- メニュー構成は「ホーム」、「子画面」
- 「子画面」が表示されていたらリロード処理(NavController#navigate)する
- リロード後に画面を2回転させるとonSaveInstanceStateでViewModelメンバ変数がnullで死亡
解決
NavControllerをいじってダメだったため、ユーザ操作をエミュレートしてやれば動くと想像 ⇒ \(^o^)/
//MainActivity内に以下のメソッドを作成する。
/** ナビゲーションによって表示されている画面をリロードする */
public void reloadDestination(){
final @NonNull NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment); //コントローラ
final @Nullable NavDestination currentDestination = navController.getCurrentDestination(); //現在の画面
final @NonNull NavigationView navigationView = findViewById(R.id.nav_view); //メニュー
if(currentDestination!=null) {
final @Nullable MenuItem item = navigationView.getMenu().findItem(currentDestination.getId()); //MenuItem逆引き
if (item != null) { //逆引き成功
NavigationUI.onNavDestinationSelected(item, navController);
//navController.navigate(resId); 直接navigateを呼び出すとバグる
}
}
}
/** ナビゲーションによって表示されている画面をリロードする
* @param matchIDs リロード対象の画面、一致しなければ何もしない
*/
public void reloadDestination(int... matchIDs){
final @NonNull NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment); //コントローラ
final @Nullable NavDestination currentDestination = navController.getCurrentDestination(); //現在の画面
final @NonNull NavigationView navigationView = findViewById(R.id.nav_view); //メニュー
if(currentDestination!=null) {
for (int resId : matchIDs) {
if (currentDestination.getId() == resId) { //現在の画面と引数が一致
final @Nullable MenuItem item = navigationView.getMenu().findItem(resId); //MenuItem逆引き
if (item != null) { //逆引き成功
NavigationUI.onNavDestinationSelected(item, navController);
//navController.navigate(resId); 直接navigateを呼び出すとバグる
}
}
}
}
}