Android 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

由于某些原因,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.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>