Android onClick无法在MVVM中使用数据绑定
由于某些原因,onClick没有在我的适配器中注册。我使用的是MVVM模式,我已经确保所有的部分都绑在一起,但就我的一生而言,我不明白为什么这不起作用 存储碎片Android onClick无法在MVVM中使用数据绑定,android,android-fragments,kotlin,mvvm,onclick,Android,Android Fragments,Kotlin,Mvvm,Onclick,由于某些原因,onClick没有在我的适配器中注册。我使用的是MVVM模式,我已经确保所有的部分都绑在一起,但就我的一生而言,我不明白为什么这不起作用 存储碎片 package com.example.brandroidtest.main import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View import android.view
package com.example.brandroidtest.main
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.navigation.fragment.findNavController
import com.example.brandroidtest.databinding.FragmentStoreBinding
class StoreFragment : Fragment() {
//Will Create a ViewModelProivders object of class DetailViewModel the first time viewModel is used
//Allows us to move this code from on create to the declaration
private val viewModel: StoreViewModel by lazy {
val factory = StoreViewModelFactory(requireNotNull(activity).application)
ViewModelProviders.of(this, factory).get(StoreViewModel::class.java)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
Log.i("onCreateView", "StoreFragment created")
val binding = FragmentStoreBinding.inflate(inflater)
binding.setLifecycleOwner(this)
binding.viewModel = viewModel
binding.storeList.adapter = StoreAdapter(StoreAdapter.OnClickListener {
viewModel.displayStoreDetails(it)
Log.i("inside OnClickListener", "after displayDetails")
})
Log.i("between adapter.onclick", "and viewModel observe")
viewModel.selectedStore.observe(this, Observer {
Log.i("observe", "inside the selectedStore observe method")
if (null != it) {
this.findNavController().navigate(
StoreFragmentDirections.actionMainListFragmentToDetailFragment(
it
)
)
viewModel.displayStoreDetailsComplete()
}
})
return binding.root
}
}
StoreViewModel
package com.example.brandroidtest.main
import android.app.Application
import android.content.Context
import android.net.ConnectivityManager
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.example.brandroidtest.model.Store
import com.example.brandroidtest.network.StoreAPI
import kotlinx.coroutines.*
enum class StoreAPIStatus {LOADING, DONE, NO_CONNECTION}
class StoreViewModel(application: Application) : AndroidViewModel(application) {
// Response from server: Either Store Data or Failure Message
private val _status = MutableLiveData<StoreAPIStatus>()
// for status of get request
//displayed when there is no internet connection or if the connection is unstable and the data is being loaded
val status: LiveData<StoreAPIStatus>
get() = _status
//internal variable accessed within this file
private val listOfStores = MutableLiveData<List<Store>>()
//external variable for anywhere else
val stores: LiveData<List<Store>>
get() = listOfStores
private val _selectedStore = MutableLiveData<Store>()
val selectedStore: LiveData<Store>
get() = _selectedStore
private var viewModelJob = Job()
private val coroutineScope = CoroutineScope(viewModelJob + Dispatchers.Main)
/**
* Call getStoreData() in init so we can display the result immediately.
*/
init {
Log.i("viewModel init", "inside StoreViewModel init block")
if (isNetworkConnected(application.applicationContext))
getStoreData()
else
// Log.i("Bypassed network call", "")
listOfStores.value = emptyList()
_status.value = StoreAPIStatus.NO_CONNECTION
}
/**
* Sets the value of the status LiveData to the Store API data.
*/
private fun getStoreData() {
Log.i("getStoreData()", " inside getStoreData")
coroutineScope.launch {
try {
Log.i("getStoreData()", "Inside the coroutine before getData")
_status.value = StoreAPIStatus.LOADING
var storeData = async { StoreAPI.retrofitService.getData().stores }.await()
Log.i("getStoreData()", "Inside the coroutine after getData")
_status.value = StoreAPIStatus.DONE
listOfStores.value = storeData
} catch (e: Exception) {
_status.value = StoreAPIStatus.NO_CONNECTION
listOfStores.value = ArrayList()
e.printStackTrace()
}
}
}
override fun onCleared() {
super.onCleared()
viewModelJob.cancel()
}
private fun isNetworkConnected(context: Context): Boolean {
val cm =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
return cm!!.activeNetworkInfo != null && cm.activeNetworkInfo.isConnected
}
//will be called to set the store as the one that was clicked
fun displayStoreDetails(store : Store){
Log.i("displayStoreDetails", "inside this method")
_selectedStore.value = store
}
//sets the selected store's value to null so that live data can be updated when we select a new store and not show us the detail apge of the same store
fun displayStoreDetailsComplete() {
Log.i("displayStoreDetailsComplete", "inside this method")
_selectedStore.value = null
}
}
StoreDetailViewModel
package com.example.brandroidtest.detailed
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.example.brandroidtest.model.Store
class StoreDetailViewModel(store: Store, application: Application) : AndroidViewModel(application) {
private val _selectedStore = MutableLiveData<Store>()
val selectedStore : LiveData<Store>
get() = _selectedStore
init {
_selectedStore.value = store
}
}
package com.example.brandroidtest.detailed
导入android.app.Application
导入androidx.lifecycle.AndroidViewModel
导入androidx.lifecycle.LiveData
导入androidx.lifecycle.MutableLiveData
导入com.example.brandroidtest.model.Store
类StoreDetailViewModel(商店:商店,应用程序:应用程序):AndroidViewModel(应用程序){
private val_selectedStore=MutableLiveData()
val selectedStore:LiveData
get()=\u selectedStore
初始化{
_selectedStore.value=store
}
}
我不知道为什么onClick不起作用,细节片段也不会因此显示出来
以下是项目链接:问题来自适配器项布局。 每个项目的高度显示为
wrap\u content
。但是您正在使用滚动视图
作为项目视图的根视图。
删除无用的滚动视图
,以及下一个线性布局
。您的布局应该如下所示:
<LinearLayout
...
android:padding="16dp"/>
<ImageView
android:id="@+id/store_logo"
.../>
<LinearLayout
android:id="@+id/store_detail"
...>
</LinearLayout>
要触发从适配器
到片段
的回调,我建议使用接口
,而不是class@DuyKhanhNguyen你能告诉我怎么做吗?本教程做的事情和它的工作原理完全相同,但对我来说不会。这里有一个使用接口的例子。你可以考虑<代码>片段<代码>作为你的代码>适配器<代码>:没有任何事情发生,我得到相同的结果。你能在你的本地系统上查一下吗?好的。让我检查一下,我明白了,问题来自你的商店商品布局。检查我的更新,知道了吗,修好了!我不知道为什么我一直把它放在滚动视图中!主要原因是布局是从其他文件克隆的
package com.example.brandroidtest.detailed
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.example.brandroidtest.model.Store
class StoreDetailViewModel(store: Store, application: Application) : AndroidViewModel(application) {
private val _selectedStore = MutableLiveData<Store>()
val selectedStore : LiveData<Store>
get() = _selectedStore
init {
_selectedStore.value = store
}
}
<LinearLayout
...
android:padding="16dp"/>
<ImageView
android:id="@+id/store_logo"
.../>
<LinearLayout
android:id="@+id/store_detail"
...>
</LinearLayout>