简体   繁体   中英

LiveData not being set, observer never being called

I'm trying to save an "Episode" in my MainViewModel and allow other Fragments to have access to it via that ViewModel .

In MainActivity I'm observing changes in the ViewModel , which is never being triggered. Weirdly, it works fine for my MainFeed RSS object

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")
    })
}

Here's the 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
    }
}

In my EpisodesFragment I'm passing MainViewModel to a RecyclerView adapter. In the layout for the Episode item I have an onClick() that calls mViewModel.setEpisode(episode)

So the clicks are registering. I set breakpoints and can see the episode item is actually there and holds data in the setEpisode() method. It just never actually gets set in the LiveData . I verified that the ViewModel is not null in any locations I've used it.

Edit: Adding code for 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()
        })
    }
}

Try to use activity property instead of this in your EpisodesFragment when you are requesting MainViewModel :

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

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

    // ...
}

ViewModelProviders.of may return different MainViewModel instance for fragment.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM