Android:变量在Fragment中初始化后,在ViewModel中未初始化



我的片段中有一个回调方法,它是从它的ViewModel中调用的。它初始化片段的OnCreateView()方法中的变量,但当ViewModel调用它来使用它时,它为null。

我在想,这可能与虚拟机以某种方式被重新创建有关?我好像就是想不通。

以下是VM如何驱动UI的答案。他们提供了谷歌正在创建的回调接口的示例(TasksNavigator.java(,覆盖视图中的方法(TasksActivity.java(然后从VM调用该方法(TasksViewModel.java(但似乎对我不起作用。

碎片

class SearchMovieFragment : Fragment(), SearchNavigator {
companion object {
fun newInstance() = SearchMovieFragment()
}
private lateinit var searchMovieFragmentViewModel: SearchMovieFragmentViewModel
private lateinit var binding: SearchMovieFragmentBinding
private lateinit var movieRecyclerView: RecyclerView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
searchMovieFragmentViewModel = ViewModelProvider(this).get(SearchMovieFragmentViewModel::class.java)
binding = DataBindingUtil.inflate(inflater, R.layout.search_movie_fragment, container, false)
binding.viewmodel = searchMovieFragmentViewModel
searchMovieFragmentViewModel.setNavigator(this)
setUpRecyclerView(container!!.context)
return binding.root
}
private fun setUpRecyclerView(context: Context) {
movieRecyclerView = binding.searchMovieFragmentRecyclerView.apply {
this.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
}
val adapter = MovieListAdapter()
binding.searchMovieFragmentRecyclerView.adapter = adapter
searchMovieFragmentViewModel.movieList.observe(viewLifecycleOwner, Observer {
adapter.submitList(it)
})
}
override fun openDetails() {
Log.d("TEST", "opening details")
}
}

ViewModel


class SearchMovieFragmentViewModel : ViewModel(), MovieSearchItemViewModel {
private lateinit var searchNavigator: SearchNavigator
val editTextContent = MutableLiveData<String>()
var movieList = Repository.getMovieList("batman")
fun setNavigator(_searchNavigator: SearchNavigator) {
this.searchNavigator = _searchNavigator
if (searchNavigator != null) {
Log.d("TEST", "its not null $searchNavigator") // Here it is not null
}
}
private fun getMovieDetail(movieId: String) {
val movie = Repository.getMovieDetail(movieId)
Log.d("TEST", "checking ${this.searchNavigator}") // Here is where I call it but it is null
//        searchNavigator.openDetails()
}
private fun getMovieList(movieSearch: String): MutableLiveData<List<Movie>> = Repository.getMovieList(movieSearch)
override fun displayMovieDetailsButton(movieId: String) {
Log.d("TEST", "button clicked $movieId")
getMovieDetail(movieId)
}
}

回调接口

interface SearchNavigator {
fun openDetails()
}

在下面的片段方法中启动ViewModel

override onActivityCreated(@Nullable final Bundle savedInstanceState){
searchMovieFragmentViewModel = ViewModelProvider(this).get(SearchMovieFragmentViewModel::class.java)
}

我建议使用实时数据在ViewModel和Fragment之间创建连接,这将是一种更安全、正确的方法。

触发器openDetails基于实时数据中的触发器。禁止将视图(context(实例发送到ViewModel,即使对其进行包装也是如此,因为内存泄漏的可能性很高。

但是,如果您仍然想遵循这种方法,那么您应该在ViewModel中注册和注销片段实例(保留一个SearchNavigator列表(onStop()onStart()

并通过它们循环调用openDetails

最新更新