首页 > 解决方案 > MutableLiveData 在观察时返回 null

问题描述

我发送一个List模型来查看ViewModelMutableLiveData。当我记录其中设置的值时,ViewModel它会显示数据列表,但是当我想在片段中使用它们并且使用Observe它时返回 null。

片段类:

class HomeFragment : Fragment() {


lateinit var bindingFragment: FragmentHomeBinding

private lateinit var fillAllCafeList: MutableLiveData<List<ModelAdapterRecCafeList>>

private lateinit var viewModel: ViewModelHomeFragment

private lateinit var tabLayout: TabLayout
private lateinit var vpCafeList: ViewPager


override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    // Inflate the layout for this fragment
    bindingFragment =
        DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false)

    bindingFragment.lifecycleOwner = this

    viewModel = ViewModelHomeFragment()

    return bindingFragment.root
}

private fun bindView() {

    tabLayout = bindingFragment.tabLayout
    vpCafeList = bindingFragment.vpCafeList

}


override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    bindView()

    setVpCafeListHome()
    setupVpCafeListWithTabLayout()


}

//     get data from viewModel with liveData
private fun getAllCafeLsitFromViewModel(): List<ModelAdapterRecCafeList> {

    viewModel = ViewModelProvider(requireActivity()).get(
        ViewModelHomeFragment::class.java
    )

    fillAllCafeList = viewModel.listAllCafe()

    var lsAll: List<ModelAdapterRecCafeList>? = null

    fillAllCafeList.observe(viewLifecycleOwner, {

        if (it != null) {
            lsAll = it
        }

    })

    Log.d("listObserve2", "$lsAll")
    return lsAll!!
}

private fun setVpCafeListHome() {

    val lsAll = getAllCafeLsitFromViewModel()


    val ls: List<ModelAdapterVpCafeList> = arrayListOf(

        ModelAdapterVpCafeList("همه"),
        ModelAdapterVpCafeList("نزدیک من"),
        ModelAdapterVpCafeList("باز")

    )


    val vpAdapter = AdapterVpCafeList(ls, lsAll)

    vpCafeList.adapter = vpAdapter

}

private fun setupVpCafeListWithTabLayout() {

    tabLayout.setupWithViewPager(vpCafeList)

}

private fun getViewModelFactory(): ViewModelFactoryHomeFragment {
    return ViewModelFactoryHomeFragment()
}


override fun onAttach(context: Context) {
    super.onAttach(context)

}


}

视图模型:

class ViewModelHomeFragment() : ViewModel() {

lateinit var ls: MutableLiveData<List<ModelAdapterRecCafeList>>

init {
    ls = MutableLiveData()
}


/**
 * @return List<ModelAdapterRecCafeList> to view
 */
fun listAllCafe(): MutableLiveData<List<ModelAdapterRecCafeList>> {

    val lsAll = arrayListOf<ModelAdapterRecCafeList>()

    lsAll.add(
        ModelAdapterRecCafeList(
            1,
            "cafename",
            "ali",
            4.2f,
            "adress khione",
            "2",
            0,
            0,
            "x",
            0
        )
    )

    ls.value = lsAll
    Log.d("listObserve", "${ls.value} !!")
    return ls

}

override fun onCleared() {
    super.onCleared()
}

}

崩溃日志:

java.lang.RuntimeException: Unable to start activity ComponentInfo{ir.arinateam.cafechejori/ir.arinateam.cafechejori.view.MainActivity}: android.view.InflateException: Binary XML file line #13 in ir.arinateam.cafechejori:layout/activity_main: Binary XML file line #13 in ir.arinateam.cafechejori:layout/activity_main: Error inflating class fragment
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3313)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3462)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2049)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:224)
    at android.app.ActivityThread.main(ActivityThread.java:7565)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
 Caused by: android.view.InflateException: Binary XML file line #13 in ir.arinateam.cafechejori:layout/activity_main: Binary XML file line #13 in ir.arinateam.cafechejori:layout/activity_main: Error inflating class fragment
 Caused by: android.view.InflateException: Binary XML file line #13 in ir.arinateam.cafechejori:layout/activity_main: Error inflating class fragment
 Caused by: java.lang.NullPointerException
    at ir.arinateam.cafechejori.view.fragments.HomeFragment.getAllCafeLsitFromViewModel(HomeFragment.kt:109)
    at ir.arinateam.cafechejori.view.fragments.HomeFragment.setVpCafeListHome(HomeFragment.kt:114)
    at ir.arinateam.cafechejori.view.fragments.HomeFragment.onViewCreated(HomeFragment.kt:71)
    at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2987)
    at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
    at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3126)
    at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3063)
    at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2988)
    at androidx.fragment.app.FragmentStateManager.ensureInflatedView(FragmentStateManager.java:392)
    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:281)
    at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:140)
    at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
    at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:319)
    at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:298)
    at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1073)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1001)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:965)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:1127)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:686)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:538)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:481)
    at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:696)
    at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:170)
2021-03-31 17:33:33.852 18849-18849/? E/AndroidRuntime:     at androidx.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:303)
        at androidx.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:284)
        at ir.arinateam.cafechejori.view.MainActivity.onCreate(MainActivity.kt:31)
        at android.app.Activity.performCreate(Activity.java:7916)
        at android.app.Activity.performCreate(Activity.java:7903)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3288)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3462)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2049)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:224)
        at android.app.ActivityThread.main(ActivityThread.java:7565)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

标签: androidandroid-livedataandroid-viewmodelandroid-mvvm

解决方案


视图模型应如下所示:

    class ViewModelHomeFragment : ViewModel() {

   private var ls: MutableLiveData<List<ModelAdapterRecCafeList>> = MutableLiveData()
   val cafeListLiveData: LiveData<List<ModelAdapterRecCafeList>>
   get() = ls
// Customize data class as per your requirement........

data class ModelAdapterRecCafeList(val a: Int, val b: String,val c: String, var d:Float, val e: String,
    val f: String, val g: Int,val h: Int, val i: String, val j: Int)
    /**
     * @return List<ModelAdapterRecCafeList> to view
     */
    fun initCafeList() {

        val lsAll = arrayListOf<ModelAdapterRecCafeList>()

        // Just creating 5 distinct object to check live data
        for (i in 0..5){
            lsAll.add(
                ModelAdapterRecCafeList(
                    i,
                    "cafename $i",
                    "ali",
                    4.2f,
                    "adress khione",
                    "2",
                    0,
                    0,
                    "x",
                    0
                )
            )
        }

        ls.value = lsAll
        Log.d("tag==>>", "${ls.value}")
    }
}

观察片段中的实时数据,例如:

private lateinit var viewModelHomeFragment: ViewModelHomeFragment

override fun onCreateView(
  inflater: LayoutInflater,
  container: ViewGroup?,
  savedInstanceState: Bundle?
): View? {
  viewModelHomeFragment =
          ViewModelProvider(this).get(ViewModelHomeFragment::class.java)
  val root = inflater.inflate(R.layout.fragment_dashboard, container, false)

  viewModelHomeFragment.cafeListLiveData.observe(viewLifecycleOwner, Observer {
    Log.d("tag==>>","Observed Cafe list size = ${it.size}")
    //  Now notify recycler view adapter here......
  })
  viewModelHomeFragment.initCafeList()
  return root
}

推荐阅读