android - 如何使用数据绑定将回收站视图与活动绑定?
问题描述
我对数据绑定部分感到震惊。我有一个简单的应用程序,我在其中使用 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>
解决方案
在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>
推荐阅读
- node.js - 如何构建 npm 依赖项以在 Dockerfile 中使用?
- json - 删除 UTF-8 Azure 存储 Blob JSON 中的 BOM,留下不可用的 JSON
- python - Selenium problem in VS Code Interactive Mode
- django - Django Rest Framework - Account Verification Email: send_mail() works in console but not using SMTP
- php - PHP 我想将导航栏中的按钮限制为仅限管理员用户
- vue.js - 使用计算设置器时的 Vue v-model 问题
- python - I can't figure out how to save the score on this dice game I've made. What should I change?
- docker - Docker Airflow location of airflow config file
- php - PDO could not find driver & other weird errors
- c# - Assembly rename and Xaml resources