ANDROID 如何通过适配器将 mutableLiveData 绑定到我的 Recyclerview

Posted

技术标签:

【中文标题】ANDROID 如何通过适配器将 mutableLiveData 绑定到我的 Recyclerview【英文标题】:ANDROID How do i bind my mutableLiveData through an adapter to my Recyclerview 【发布时间】:2021-11-17 01:22:46 【问题描述】:

首先对不起我的英语不好。 我正在尝试在我的 android APP 中从我自己编写的 Python 后端(REST-API)接收数据。

ApiService.kt:

    private const val Base_URL = "http://192.168.178.93:5000/api/"
private val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

private val retrofit = Retrofit.Builder()
    .addConverterFactory(MoshiConverterFactory.create(moshi))
    .baseUrl(Base_URL)
    .build()

interface TodoApiService
    @GET("todo")
    suspend fun getToDo(): List<ToDo>


object ToDoApi
    val retrofitService : TodoApiService by lazy 
        retrofit.create(TodoApiService::class.java)
    

MainActivityViewModel.kt:

class MainActivityViewModel : ViewModel() 
    of the most recent request
    private val _status = MutableLiveData<String>()


val status: LiveData<String> = _status

private val _toDo = MutableLiveData<List<ToDo>>()

val toDo: LiveData<List<ToDo>> = _toDo

init 
    getToDo()


private fun getToDo() 
    viewModelScope.launch
        try 
            _toDo.value = ToDoApi.retrofitService.getToDo()
            _status.value = "Success $_toDo"
        catch (e: Exception)
            _status.value = "Failure $e.message"
        
    



activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout 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"
    android:layout_
    android:layout_
    tools:context=".MainActivity"
    >


    <androidx.recyclerview.widget.RecyclerView

        android:scrollbars="vertical"
        android:layout_
        android:layout_
        android:id="@+id/recycler_view"
        tools:listitem="@layout/todo_item"/>
</FrameLayout>

tod​​o_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:layout_marginEnd="8dp"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp">

    <RelativeLayout
        android:layout_
        android:layout_
        android:padding="8dp">
        <TextView
            android:id="@+id/text_view_name"
            android:layout_
            android:layout_
            android:text="1"/>

    </RelativeLayout>

</androidx.cardview.widget.CardView>

TodoAdapter.kt

class TodoAdapter(private val context: Context, private val Items: List<ToDo>):RecyclerView.   Adapter<TodoAdapter.TodoViewHolder>()

    class TodoViewHolder(private val view: View) : RecyclerView.ViewHolder(view)
        val textView: TextView = view.findViewById(R.id.text_view_name)

    

    override fun getItemCount() = Items.size

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder 
        val adapterLayout = LayoutInflater.from(parent.context)
            .inflate(R.layout.todo_item, parent, false)
        return TodoViewHolder(adapterLayout)
    

    override fun onBindViewHolder(holder: TodoViewHolder, position: Int) 
        val ToDo = Items.get(position)
        holder.textView.text =  context.resources.getString(ToDo.Id.toInt())

    

MainActivity.kt:

class MainActivity : AppCompatActivity() 


    private val viewModel = MainActivityViewModel()
    private lateinit var binding: ActivityMainBinding
    private lateinit var linearLayoutManager: LinearLayoutManager

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        linearLayoutManager = LinearLayoutManager(this)
        binding.recyclerView.layoutManager = linearLayoutManager
        binding.recyclerView.adapter = TodoAdapter(this, viewModel.toDo.value)

    

我知道我需要一个适配器来将我的 LiveData 连接到我的 recyclerView。但我无法正确实施。 Android Studio 告诉我,我不能将 MutableLiveData 用于只需要一个普通列表的适配器(必需:找到的列表:列表?。我无法投射,因为数据可能为空。

【问题讨论】:

【参考方案1】:

您对 LiveData 的使用不正确。您将其用作简单变量,将其当前值(为空)传递给适配器。 LiveData 用于数据流,需要观察。

我喜欢为 Adapter 类上的数据添加一个 setter:

fun setData(data: List<ToDo>) 
    Items = data
    notifyDataSetChanged()

并在 Activity 中观察 ViewModel 的实时数据,并在新数据到达时更新适配器:

class MainActivity : AppCompatActivity() 

    private lateinit var adapter: TodoAdapter

    override fun onCreate(savedInstanceState: Bundle?) 
        ...
        adapter = TodoAdapter(this)
        viewModel.todo.observe(this,  todos ->
            adapter.setData(todos)
         
    

    ...

现在,当您在 ViewModel 中为 LiveData 设置值时,将通知适配器。

【讨论】:

【参考方案2】:

这是因为您正在从活动向适配器发送一个可能为空的列表。你必须这样做:

binding.recyclerView.adapter = TodoAdapter(this, viewModel.toDo?.value ?: listOf())

【讨论】:

以上是关于ANDROID 如何通过适配器将 mutableLiveData 绑定到我的 Recyclerview的主要内容,如果未能解决你的问题,请参考以下文章

如何将值从基本适配器传递到 Android 中的 Activity

如何将最新数据附加到android中的自定义基本适配器列表视图?

如何将 getIntent.getStringExtra("username") 放入 android 适配器 onBindViewHolder(@NonNull final Vi

通过适配器在片段之间传递数据(Kotlin Android)

Android中GridView通过自定义适配器实现图文视图排列

如何在android中使用api将多个选中的复选框值传递给服务器?