首页 > 解决方案 > 如何使用数据绑定将回收站视图与活动绑定?

问题描述

我对数据绑定部分感到震惊。我有一个简单的应用程序,我在其中使用 mvvm 模式来显示列表。但问题是如何将带有 id recycler_view 的回收器视图与活动绑定

//数据类

data class MovieItem(

val imageUrl: String,
val name: String

)

// 存储库

class MovieRepository(private val api: Api) {

suspend fun getAllMovies() = api.getMovieList()

}

// 查看模型

class MovieViewModel(private val repository: MovieRepository):ViewModel() {


var listMovie = MutableLiveData<List<MovieItem>>()
var job: Job? = null



fun makeApiCall(){

    job= CoroutineScope(Dispatchers.IO).launch {
        var response = repository.getAllMovies()
        withContext(Dispatchers.Main){

            if (response != null){
                listMovie.postValue(response.body())
            }
        }
    }
}

}

// 适配器

类 MovieItemAdapter:RecyclerView.Adapter<MovieItemAdapter.MovieViewHolder>() {

var listMovie = mutableListOf<MovieItem>()
private val context:Context ? = null

fun setMovieItem(data : List<MovieItem>){
    this.listMovie = data.toMutableList()
    notifyDataSetChanged()

}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {

    val binding = DataBindingUtil.inflate<MovieItemBinding>(LayoutInflater.from(parent.context),
        R.layout.movie_item,parent,
        false)
    return MovieViewHolder(binding)
}

override fun onBindViewHolder(holder: MovieViewHolder, position: Int) =

override fun getItemCount(): Int {
    return listMovie.size
}


class MovieViewHolder(val binding: MovieItemBinding):RecyclerView.ViewHolder(binding.root){


  fun bind(item : MovieItem){

      binding.model = item
  }



}

}

// 活动

类 MainActivity : AppCompatActivity() {

lateinit var movieadapter: MovieItemAdapter
lateinit var api: Api
lateinit var repository: MovieRepository
lateinit var movieViewModel: MovieViewModel


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)


    var recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
    recyclerView.layoutManager = LinearLayoutManager(this)
    movieadapter = MovieItemAdapter()
    recyclerView.adapter = movieadapter


    api = Api.getInstance()
    repository = MovieRepository(api)


    movieViewModel = ViewModelProvider(this, MovieFactory(repository))
        .get(MovieViewModel::class.java)

    movieViewModel.makeApiCall()
    movieViewModel.listMovie.observe(this, Observer {
        movieadapter.setMovieItem(it)
    })

}

}

// 适配器布局

<layout xmlns:android="http://schemas.android.com/apk/res/android">

<data>
    <variable
        name="model"
        type="com.example.databindingpractice.MovieItem" />

</data>

<androidx.cardview.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:padding="3dp"
        android:orientation="horizontal">


        <ImageView
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:id="@+id/img_view" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="@color/black"
            android:textSize="18sp"
            android:text="@{model.name}"
            android:layout_marginLeft="5dp"
            android:id="@+id/tv_view"
            android:layout_gravity="center" />


    </LinearLayout>

</androidx.cardview.widget.CardView>
<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>
    
    <variable
        name="activity"
        type="com.example.databindingpractice.MainActivity" />

</data>

<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/recycler_view" />


</LinearLayout>

标签: androidkotlindata-bindingkotlin-coroutinesandroid-databinding

解决方案


onCreate方法中Activity,替换

setContentView(R.layout.activity_main)

val binding : MainActivityBinding =
    DataBindingUtil.setContentView(this, R.layout.activity_main)

然后你可以使用

binding.recyclerView.layoutManager = LinearLayoutManager(this)
movieadapter = MovieItemAdapter()
binding.recyclerView.adapter = movieadapter

还要从 activity_main.xml 中删除它

<data>
    
    <variable
        name="activity"
        type="com.example.databindingpractice.MainActivity" />

</data>

以此作为参考

更新: 绑定适配器可以定义如下:

@BindingAdapter("moviesList")
fun bindRecyclerView(recyclerView: RecyclerView, list: List<MovieItem>?){
    val adapter: MoviesAdapter = recyclerView.adapter as MoviesAdapter
    adapter.submitList(list)
}

在 activity_main.xml

<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>
    
    <variable
        name="viewModel"
        type="com.example.databindingpractice.MovieViewModel" />

</data>

<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/recycler_view" 
        app:movieList="@{viewModel.listMovie}"/>


</LinearLayout>

推荐阅读