Android ViewModel 不兼容的回调和捆绑范围

Android ViewModel incompatible callback and bundle scope

提问人:Nexussim Lements 提问时间:5/8/2023 更新时间:5/8/2023 访问量:17

问:

当用户在我的 MainActivity 中与 TextView 交互时,我调用一个,并向它传递一个可用游戏列表,以便用户可以选择一个:GamesBottomSheetDialog

@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {

   ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        gamesViewModel = new ViewModelProvider(this).get(GamesViewModel.class);
        gamesViewModel.getSelectedGame().observe(this, new Observer<Game>() {
            @Override
            public void onChanged(Game game) {
                //WAIT FOR THE USER TO SELECT A GAME FROM THE BOTTOM SHEET LIST
            }
        });
        initializeGameSelectorDialog();
    }

    private void initializeGameSelectorDialog() {
        binding.preview.tvGames.setOnClickListener(view -> {
            gamesBottomSheetDialog = GamesBottomSheetDialog.newInstance();
            Bundle bundle = new Bundle();
            bundle.putSerializable(GAMES, getAvailableGames());
            gamesBottomSheetDialog.setArguments(bundle);
            gamesBottomSheetDialog.show(getSupportFragmentManager(), "ModalBottomSheet");
        });
    }
    
    ...

}

然后我简单地实例化一个并观察游戏,直到它们被分组(自定义逻辑)并准备好在适配器中显示:GamesBottomSheetDialogGamesViewModel

    @AndroidEntryPoint
    public class GamesBottomSheetDialog extends BottomSheetDialogFragment {
        
        private GamesAdapter gamesAdapter;
    
        private GamesViewModel viewModel;
        private BottomSheetGamesBinding binding;
    
        public GamesBottomSheetDialog() {
            //REQUIRED EMPTY CONSTRUCTOR
        }
    
        public static GamesBottomSheetDialog newInstance() {
            return new GamesBottomSheetDialog();
        }
    
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            binding = BottomSheetGamesBinding.inflate(getLayoutInflater());
            viewModel = new ViewModelProvider(requireActivity()).get(GamesViewModel.class);
            viewModel.getGameItems().observe(getViewLifecycleOwner(), new Observer<List<GameItem>>() {
                @Override
                public void onChanged(List<GameItem> gameItems) {
                    GenericUtils.changeVisibility(View.GONE, binding.progressBar);
                    gamesAdapter.refreshAdapter(gameItems);
                }
            });
            ...
            return binding.getRoot();
        }

     ...

      //This method is a callback listener from the adapter:
     @Override 
public void onGameSelected(Game game) {
                gamesViewModel.setGame(game);
        }

    }

由于我需要在用户点击适配器内的游戏项目时提供回调,因此我需要创建一个附加到 Activity 范围的“Shared ViewModel”:MainActivityGamesBottomSheetDialog

@HiltViewModel
public class GamesViewModel extends ViewModel {

    ...

    @Inject
    GamesViewModel(GameRepository gameRepository, SavedStateHandle savedStateHandle){
        this.gameRepository = gameRepository;

        GameList gameList = GenericUtils.deserialize(savedStateHandle.get(GAMES), GameList.class);
        if (Objects.nonNull(gameList)) {
            games = gameList.getGameList();
        }
        selectedGame = new MutableLiveData<>();
        gameItems = new MutableLiveData<>();
        
        gameItems.setValue(groupGames(games));

    }

    ...

    public MutableLiveData<List<GameItem>> getGameItems() {
        return gameItems;
    }

    public MutableLiveData<Game> getSelectedGame() {
        return selectedGame;
    }

    public void setGame(Game game) {
        selectedGame.setValue(game);
    }
 
}

但是,这里存在一个很大的不兼容问题,如果我将 ViewModel 范围设置为活动,则回调可以完美运行,但是预填充游戏列表的回调始终为 null,因为 Bundle 的范围限定为 Fragment 本身而不是 Activity。这意味着,如果我从这里更改范围:SavedStateHandleGamesViewModel

 viewModel = new ViewModelProvider(requireActivity()).get(GamesViewModel.class);

对此:

 viewModel = new ViewModelProvider(this).get(GamesViewModel.class);

in ViewModel 不再是 null,但现在回调不起作用,因为 的作用域与位于 中的作用域不同。SavedStateHandleMainActivityGamesBottomSheetDialog

有没有办法以兼容的方式使用我的 Bundle 和回调?

mvvm 回调 android-viewmodel dagger-hilt

评论


答: 暂无答案