【问题标题】:LiveData not being set, observer never being calledLiveData 未设置,观察者从未被调用
【发布时间】:2019-06-10 23:44:26
【问题描述】:

我正在尝试在我的 MainViewModel 中保存一个“剧集”,并允许其他 Fragments 通过该 ViewModel 访问它。

MainActivity 中,我正在观察ViewModel 的变化,它从未被触发。奇怪的是,它适用于我的 MainFeed RSS 对象

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(MainViewModel::class.java)


    mViewModel?.getMainFeed()

    setFragment(EpisodesFragment(), false)

    mViewModel?.episode?.observe(this, Observer {
        Log.d(TAG, "HERE 123")
    })
}

这是MainViewModel

class MainViewModel @Inject constructor(): ViewModel() {
    val TAG: String? = MainViewModel::class.simpleName

    @Inject lateinit var api: NetworkModule

    var mainFeed: MutableLiveData<Response<RSS>> = MutableLiveData()
    var episode: MutableLiveData<Item> = MutableLiveData()

    companion object{
        fun create(activity: FragmentActivity, viewModelFactory: ViewModelProvider.Factory): MainViewModel {
            return ViewModelProviders.of(activity, viewModelFactory).get(MainViewModel::class.java)
        }
    }

    fun getMainFeed(){
        GlobalScope.launch(Dispatchers.Main) {
            val request = api.getRssFeed()
            val response = request.await()

            if(response.isSuccessful){
                Log.d(TAG, "isSuccessful")

                mainFeed.value = response
            } else {
                Log.d(TAG, "not successful")
            }
        }
    }

    fun setEpisode(item: Item?){
        Log.d(TAG, item?.description)
        episode?.value = item
    }
}

在我的EpisodesFragment 中,我将MainViewModel 传递给RecyclerView 适配器。在剧集项目的布局中,我有一个 onClick() 调用 mViewModel.setEpisode(episode)

所以点击正在注册。我设置了断点,可以看到剧集项目实际上在那里,并在 setEpisode() 方法中保存数据。它只是从未真正在LiveData 中设置。我验证了ViewModel 在我使用过的任何位置都不为空。

编辑:为 EpisodesFragment 添加代码

class EpisodesFragment @Inject constructor() : DaggerFragment() {
    var TAG: String? = EpisodesFragment::class.simpleName

    var mBinding: FragmentEpisodesBinding? = null
    var mRV: RecyclerView? = null
    var mAdapter: EpisodesRecyclerViewAdapter? = null

    var mItems: MutableList<Item> = ArrayList<Item>()

    @Inject
    lateinit var mViewModelFactory: ViewModelProvider.Factory
    var mViewModel: EpisodesViewModel? = null
    var mMainViewModel: MainViewModel? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        super.onCreateView(inflater, container, savedInstanceState)

        mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_episodes, container, false)
        mBinding?.executePendingBindings()


        return mBinding?.root
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        mViewModel = ViewModelProviders.of(this,
            mViewModelFactory
        ).get(EpisodesViewModel::class.java)

        mMainViewModel = ViewModelProviders.of(
            this,
            mViewModelFactory
        ).get(MainViewModel::class.java)

        if (mBinding?.rv != null) {
            mRV = mBinding?.rv
            val context: Context? = mRV?.context

            mRV?.setHasFixedSize(true)

            mAdapter = EpisodesRecyclerViewAdapter(mMainViewModel)

            mRV?.adapter = mAdapter

            val layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
            val dividerItemDecoration = DividerItemDecoration(
                mRV?.context,
                layoutManager.orientation
            )
            mRV?.addItemDecoration(dividerItemDecoration)
            mRV?.layoutManager = layoutManager

        }

        mViewModel?.getMainFeed()

        mViewModel?.mainFeed?.observe(viewLifecycleOwner, Observer {
            mItems.addAll(it?.body()?.channel?.item!!)

            Log.d(TAG, mItems.get(0).description)
            mAdapter?.setItems(mItems)
            mAdapter?.notifyDataSetChanged()
        })
    }
}

【问题讨论】:

  • 我猜你可以在这里完成问号mViewModel?,bcz ViewModelProviders.of() 将始终返回ViewModel
  • GlobalScope.launch 不推荐使用,应该使用本地范围来启动协程。
  • 能否提供EpisodesFragment的代码
  • 好的,我会编辑的。

标签: android mvvm kotlin android-livedata


【解决方案1】:

当您请求MainViewModel 时,尝试在EpisodesFragment 中使用activity 属性而不是this

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)

    mMainViewModel = ViewModelProviders.of(
        activity,
        mViewModelFactory
    ).get(MainViewModel::class.java)

    // ...
}

ViewModelProviders.of 可能会为片段返回不同的MainViewModel 实例。

【讨论】:

  • 是的。这行得通。我可以发誓我早些时候尝试过,但它没有用,但它现在可以工作了。谢谢!
  • 如果你来自 Java 会很有趣 - 这让我很着迷 - 它适用于 Java 中的本地上下文 (this)
猜你喜欢
  • 2018-07-22
  • 1970-01-01
  • 1970-01-01
  • 2019-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多