0

我正在尝试使用 Kotlin 在 RecyclerView 中查看列表。我正在片段类中编写 RecyclerView id 并在适配器中设置列表(响应),但它没有显示在 RecyclerView 中。下面的代码是写的我不知道我该如何解决这个问题。

项目有一个 Fragment、Adapter、xml 文件和模型类。

fragment_availabletender

这个页面有 RecyclerView。

            <?xml version="1.0" encoding="utf-8"?>
            <layout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                xmlns:tools="http://schemas.android.com/tools">

                <!-- Data to make available to the XML via data binding. In this case,
                     the whole ViewModel, so that we can access the LiveData,
                     click handlers, and state variables. -->
                <data>
                    <variable
                        name="viewModel"
                        type= "com.bitcomm.main.ui.home.NotificationViewModel" />
                </data>

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">

                    <androidx.appcompat.widget.AppCompatSpinner
                        android:id="@+id/spinner2"
                        android:layout_width="93dp"
                        android:layout_height="39dp"
                        android:layout_alignParentRight="true"
                        android:entries="@array/array_name"
                        style="@style/spinnerItemStyle"
                        android:layout_alignParentEnd="true" />

                    <androidx.appcompat.widget.AppCompatSpinner
                        android:id="@+id/spinner1"
                        android:layout_width="93dp"
                        android:layout_height="39dp"
                        android:layout_toLeftOf="@+id/spinner2"
                        android:entries="@array/array_name1"
                        style="@style/spinnerItemStyle"
                        android:layout_toStartOf="@+id/spinner2" />

                    <androidx.recyclerview.widget.RecyclerView
                        android:id="@+id/tender_list"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:background="#0f3b52"
                        android:color="@color/cardview_light_background"
                        android:padding="6dp"
                        android:layout_below="@+id/spinner2"
                        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
                      />
                </RelativeLayout>

模型类这个类有模型

            data class TenderProperty(

                val id: String,
                // used to map img_src from the JSON to imgSrcUrl in our class
                @Json(name = "img_src") val imgSrcUrl: String,
                val type: String,
                val price: Double
            )

TenderViewModel 这里响应越来越

             private val _response = MutableLiveData<List<TenderProperty>>()

                // The external immutable LiveData for the response String
                val response: LiveData<List<TenderProperty>>
                    get() = _response

                private val _navigateToSelectedProperty = MutableLiveData<TenderProperty>()
                val navigateToSelectedProperty: LiveData<TenderProperty>
                    get() = _navigateToSelectedProperty

                // Create a Coroutine scope using a job to be able to cancel when needed
                private var viewModelJob = Job()

                // the Coroutine runs using the Main (UI) dispatcher
                private val coroutineScope = CoroutineScope(viewModelJob + Dispatchers.Main )

                /**
                 * Call getMarsRealEstateProperties() on init so we can display status immediately.
                 */
                init {
                    getTenderRealEstateProperties()
                }

                private fun getTenderRealEstateProperties() {

                    coroutineScope.launch {
                        // Get the Deferred object for our Retrofit request
                        var getPropertiesDeferred = TenderApi.retrofitService.getProperties()
                        try {
                            // this will run on a thread managed by Retrofit
                            val listResult = getPropertiesDeferred.await()

                            _sortByPrice.value=listResult.toList().sortedBy {it.price}
                            _sortById.value=listResult.toList().sortedBy {it.id}

                            _response.value = listResult
                            println("hii"+_response.value)
                            Log.d("class","_response.value")

                        } catch (e: Exception) {

                            _response.value = ArrayList()
                            Log.d("class","_response.value")
                        }
                    }
                }

                fun displayPropertyDetails(marsProperty: TenderProperty) {
                    _navigateToSelectedProperty.value = marsProperty
                }

               fun displayPropertyDetailsComplete() {
                    _navigateToSelectedProperty.value = null
                }

ListTenderAdapter 这是适配器类

            class ListTenderAdapter( private val onClickListener: OnClickListener ) :
                ListAdapter<TenderProperty,
                        ListTenderAdapter.TenderPropertyViewHolder>(DiffCallback) {


                class TenderPropertyViewHolder(private var binding:TenderListViewBinding):
                    RecyclerView.ViewHolder(binding.root) {
                    fun bind(tenderProperty: TenderProperty) {
                        binding.property = tenderProperty
                        // This is important, because it forces the data binding to execute immediately,
                        // which allows the RecyclerView to make the correct view size measurements
                        binding.executePendingBindings()
                    }
                }

                /**
                 * Allows the RecyclerView to determine which items have changed when the [List] of [MarsProperty]
                 * has been updated.
                 */
                companion object DiffCallback : DiffUtil.ItemCallback<TenderProperty>() {
                    override fun areItemsTheSame(oldItem: TenderProperty, newItem: TenderProperty): Boolean {
                        return oldItem === newItem
                    }

                    override fun areContentsTheSame(oldItem: TenderProperty, newItem: TenderProperty): Boolean {
                        return oldItem.id == newItem.id
                    }
                }

                /**
                 * Create new [RecyclerView] item views (invoked by the layout manager)
                 */
                override fun onCreateViewHolder(parent: ViewGroup,
                                                viewType: Int): TenderPropertyViewHolder {
                    return TenderPropertyViewHolder(TenderListViewBinding.inflate(LayoutInflater.from(parent.context)))
                }

                /**
                 * Replaces the contents of a view (invoked by the layout manager)
                 */
                override fun onBindViewHolder(holder: TenderPropertyViewHolder, position: Int) {
                    val tenderProperty = getItem(position)
                    holder.itemView.setOnClickListener {
                        onClickListener.onClick(tenderProperty)
                    }
                    holder.bind(tenderProperty)
                }

                /**
                 * Custom listener that handles clicks on [RecyclerView] items.  Passes the [MarsProperty]
                 * associated with the current item to the [onClick] function.
                 * @param clickListener lambda that will be called with the current [MarsProperty]
                 */
                class OnClickListener(val clickListener: (tenderProperty: TenderProperty) -> Unit) {
                    fun onClick(tenderProperty: TenderProperty) = clickListener(tenderProperty)
                }
            }

这是片段类

            class TenderListFragment : Fragment() {

                private val viewModel: NotificationViewModel by lazy {
                    ViewModelProviders.of(this).get(NotificationViewModel::class.java)
                }

                override fun onCreateView(
                    inflater: LayoutInflater,
                    container: ViewGroup?,
                    savedInstanceState: Bundle?
                ): View? {

                    val binding = FragmentAvailabletenderBinding.inflate(inflater)

                    binding.lifecycleOwner = this

                    binding.viewModel = viewModel

                    binding.tenderList.addItemDecoration(MarginItemDecoration(5))

                    val adapter=binding.tenderList.adapter as ListTenderAdapter
                    adapter.submitList(viewModel.response.value)
                    binding.tenderList.adapter = ListTenderAdapter(ListTenderAdapter.OnClickListener {
                        viewModel.displayPropertyDetails(it)
                    })
                    adapter.notifyDataSetChanged()
                    // binding.tenderList.layoutManager = LinearLayoutManager(activity)
                    setHasOptionsMenu(true)
                    return binding.root

                }
4

2 回答 2

2

在onCreateView 内的 TenderListFragment类中删除以下所有行:

binding.tenderList.addItemDecoration(MarginItemDecoration(5))

                    val adapter=binding.tenderList.adapter as ListTenderAdapter
                    adapter.submitList(viewModel.response.value)
                    binding.tenderList.adapter = ListTenderAdapter(ListTenderAdapter.OnClickListener {
                        viewModel.displayPropertyDetails(it)
                    })
                    adapter.notifyDataSetChanged()

在TenderListFragment 中将适配器声明为全局变量

private lateinit var adapter : ListTenderAdapter

并从onCreateView()

private fun setupRecyclerView(){
     binding.tenderList.addItemDecoration(MarginItemDecoration(5))
     adapter = ListTenderAdapter(ListTenderAdapter.OnClickListener {
                    viewModel.displayPropertyDetails(it)
                })
     binding.tenderList.setAdapter(adapter)

}

再添加一个方法initViewModel()并从onCreateViewafter调用它setupRecyclerView()

private fun initViewModel(){
    viewModel.response.observe(this, Observer {
       adapter.submitList(it)
    })
}
于 2020-01-31T08:20:20.527 回答
1

您没有观察实时数据的变化。您必须观察可变实时数据的变化并将列表传递给适配器在视图模型和适配器初始化后尝试此代码。也无需调用notifyDataSetChanged,因为列表适配器会相应地计算差异。

viewModel.response.observe(this, Observer {
        adapter.submitList(it)
    })
于 2020-01-31T08:18:50.623 回答