android - MutableLiveData 在观察时返回 null
问题描述
我发送一个List
模型来查看ViewModel
和MutableLiveData
。当我记录其中设置的值时,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)
解决方案
视图模型应如下所示:
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
}
推荐阅读
- python - Python:有没有更简单的方法来做这个脚本?
- maven - TestSetFailedException 仅在 Linux 上
- r - 如何不随机地估算缺失值?
- arrays - 将 PostgreSQL bigint 数组唯一值移动到另一个索引
- python - sklearn tfidf 矢量化器 - 如果存在 n 克,则删除 n-2 和 n-1 克
- css - 使用 css 的 calc + sass 计算列宽
- python - 奇怪的 numpy.array 行为 - 嵌套列表列表的错误转换或者我不明白它是如何工作的?
- node.js - 在 Node/Express 服务器中使用 async/await 是个坏主意吗?
- nativescript - 如何正确使用 someClass.android.ts 和 someClass.ios.ts
- javascript - JS中字符串类型的对象保存数组