这是我参与「第四届青训营 」笔记创作活动的第3天。
MVVM框架下实现RecyclerView
效果图
导入DataBinding引用
首先在app目录下的build.gradle文件中,android下添加
dataBinding{
enabled = true
}
导入RecyclerView引用
首先在app目录下的build.gradle文件中,dependencies下添加
implementation 'androidx.recyclerview:recyclerview:1.1.0'
代码实现
建立实体类
注意:
1.继承被观察者模式BaseObservable
2.使用@Bindable绑定字段
3.刷新数据(BR自动生成)
import android.graphics.drawable.BitmapDrawable;
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import bytedance.example.easy_tiktok.BR;
// 继承被观察者模式BaseObservable
public class MovieItem extends BaseObservable {
BitmapDrawable img;//图片
String title;//电影名称
String score;//豆瓣评分
String mark;//标记、电影类别
String timeOn;//上映时间
String hots;//热度
public MovieItem(BitmapDrawable img, String title, String score, String mark, String timeOn, String hots) {
this.img = img;
this.title = title;
this.score = score;
this.mark = mark;
this.timeOn = timeOn;
this.hots = hots;
}
// 使用@Bindable绑定字段
@Bindable
public BitmapDrawable getImg() {
return img;
}
public void setImg(BitmapDrawable img) {
this.img = img;
// 刷新数据(BR自动生成)
notifyPropertyChanged(BR.img);
}
@Bindable
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
notifyPropertyChanged(BR.title);
}
@Bindable
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
notifyPropertyChanged(BR.score);
}
@Bindable
public String getMark() {
return mark;
}
public void setMark(String mark) {
this.mark = mark;
notifyPropertyChanged(BR.mark);
}
@Bindable
public String getTimeOn() {
return timeOn;
}
public void setTimeOn(String timeOn) {
this.timeOn = timeOn;
notifyPropertyChanged(BR.timeOn);
}
@Bindable
public String getHots() {
return hots;
}
public void setHots(String hots) {
this.hots = hots;
notifyPropertyChanged(BR.hots);
}
}
UI视图XML文件
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="vm"
type="bytedance.example.easy_tiktok.vm.MainVm" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/mainRv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
建立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">
导入实体类
<data>
<variable
name="movieItems"
type="bytedance.example.easy_tiktok.bean.MovieItem" ></variable>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/movie_img"
android:layout_width="100dp"
android:layout_height="120dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
//绑定数据层
android:src="@{movieItems.img}"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="150dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/movie_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:textSize="20dp"
android:textColor="@color/black"
android:gravity="center"
android:layout_weight="0.8"
//绑定数据层
android:text="@{movieItems.title}"></TextView>
<TextView
android:id="@+id/movie_score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textSize="10dp"
android:gravity="center"
android:layout_weight="0.5"
//绑定数据层
android:text="@{movieItems.score}"></TextView>
<TextView
android:id="@+id/movie_mark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textSize="10dp"
android:gravity="center"
android:layout_weight="0.5"
//绑定数据层
android:text="@{movieItems.mark}"></TextView>
<TextView
android:id="@+id/movie_timeOn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textSize="10dp"
android:gravity="center"
android:layout_weight="0.5"
android:text="@{movieItems.timeOn}"></TextView>
<TextView
android:id="@+id/movie_hots"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="5"
android:gravity="center"
android:textSize="10dp"
//绑定数据层
android:text="@{movieItems.hots}"></TextView>
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center"
android:background="@android:color/holo_red_dark"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:text="购票">
</Button>
</LinearLayout>
</LinearLayout>
</layout>
适配器类
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.ViewHolder> {
private List<MovieItem> lists;
引入数据源
public MovieAdapter(List<MovieItem> lists) {
this.lists = lists;
}
绑定布局文件
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ViewDataBinding viewDataBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.movielistitem,parent,false);
return new ViewHolder(viewDataBinding);
}
设置数据
@Override
public void onBindViewHolder(MovieAdapter.ViewHolder holder, int position) {
MovieItem movieItem = lists.get(position);
holder.viewDataBinding.setVariable(BR.movieItems,movieItem);
holder.viewDataBinding.executePendingBindings();
}
@Override
public int getItemCount() {
return lists.size();
}
自定义ViewHolder内部类
public class ViewHolder extends RecyclerView.ViewHolder {
ViewDataBinding viewDataBinding;
public ViewHolder(ViewDataBinding viewDataBinding) {
super(viewDataBinding.getRoot());
this.viewDataBinding = viewDataBinding;
}
public ViewDataBinding getBinding(){
return viewDataBinding;
}
}
}
数据与视图交互
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding mainBinding; //绑定主布局文件
MainVm mainvm;
List<MovieItem> items = new ArrayList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//绑定布局文件
mainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
mainvm = new ViewModelProvider(this,new ViewModelProvider.NewInstanceFactory()).get(MainVm.class);
mainBinding.setVm(mainvm);
mainBinding.setLifecycleOwner(this);
因为是造的假数据,就直接写在了activity中,如果是存放数据的话,应当遵循MVVM,不得在activity中处理数据
String t = "标题";
Random r = new Random();
for (int i = 0; i < 10; i++) {
MovieItem item = new MovieItem(null,t+i,"豆瓣评分:"+r.nextInt(100),null,"上映时间","热度:"+(r.nextInt(95)*100)+"万");
items.add(item);
}
//为视图控件设置adapter,并传入list
mainBinding.mainRv.setLayoutManager(new LinearLayoutManager(this));
mainBinding.mainRv.setAdapter(new MovieAdapter(items));
}
}