前几天写了DataBind 不写adapter和viewholder了在掘金上吸取了几位大佬的建议,所以这篇文章主要是补充上文的,建议没有看过的可以考虑看一看。好了进入正文:
bean的复用
由于上次实现把layout和bean绑定一起了这就导致了bean的复用性很差,而且当只是让bean承担实体的作用时 bean会有额外的职责,很不符合单一职责原则,感谢大佬们的提醒
我的解决方案
怎么解决这个问题呢?我的解决方案很简单 就是加了一个wrapper.简单的来说,就是将实体注入wrapper,wrapper持有一个bean对象,那么layout里就可以操作bean了,同时ui的交互也交给了wrapper,保证了bean类的纯净
具体实现(主要都是贴代码)
这里由于BindAdapterType接口不是很适合需求然后我就删除了,取而代之的是LayoutWrapper
public interface LayoutWrapper<T> {
/**
* @param t 适应的目标
* @return this
*/
LayoutWrapper setTarget(T t);
/**
* @return 适应的目标
*/
T getTarget();
/**
* @return layoutId
*/
int getType();
/**
* @return layout中的 BR.id
*/
int getId();
}
为了方便阅读 这里我就多贴一些代码
实体
public class UserInfo{
private String name;
private String age;
private String avator;
//省略set/get
public UserInfo(String name, String age, String avator) {
this.name = name;
this.age = age;
this.avator = avator;
}
}
public class StudentInfo{
private String name;
private String age;
private String avator;
//省略set/get
public StudentInfo(String name, String age, String avator) {
this.name = name;
this.age = age;
this.avator = avator;
}
}
wrapper
//userItemWrapper
public class UserItemWrapper implements LayoutWrapper<UserInfo> {
private UserInfo userInfo;
@Override
public UserItemWrapper setTarget(UserInfo userInfo) {
this.userInfo = userInfo;
return this;
}
@Override
public UserInfo getTarget() {
return userInfo;
}
@Override
public int getType() {
return R.layout.user_item;
}
@Override
public int getId() {
return BR.user;
}
@BindingAdapter("avator")
public static void setUserInfoAvtor(ImageView imageView, String avator) {
Glide.with(imageView.getContext()).load(avator).into(imageView);
}
public void clickParent(View view) {
Toast.makeText(view.getContext(), "福步距", Toast.LENGTH_SHORT).show();
}
public void clickImage(View view) {
Toast.makeText(view.getContext(), "ImageView", Toast.LENGTH_SHORT).show();
}
}
//studentItemWrapper
public class StudentItemWrapper implements LayoutWrapper<StudentInfo> {
private StudentInfo studentInfo;
@Override
public StudentItemWrapper setTarget(StudentInfo studentInfo) {
this.studentInfo = studentInfo;
return this;
}
@Override
public StudentInfo getTarget() {
return studentInfo;
}
@Override
public int getType() {
return R.layout.student_item;
}
@Override
public int getId() {
return BR.student;
}
@BindingAdapter("avator")
public static void setUserInfoAvtor(ImageView imageView, String avator) {
Glide.with(imageView.getContext()).load(avator).into(imageView);
}
public void clickParent(View view) {
Toast.makeText(view.getContext(), "福步距", Toast.LENGTH_SHORT).show();
}
public void clickImage(View view) {
Toast.makeText(view.getContext(), "ImageView", Toast.LENGTH_SHORT).show();
}
}
layout
//user_item
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="user"
type="com.google.simple.model.wrapper.UserItemWrapper"
/>
</data>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{user.clickParent}"
android:padding="9dp">
<ImageView
android:id="@+id/avator"
android:layout_width="120dp"
android:layout_height="120dp"
android:onClick="@{user.clickImage}"
app:avator="@{user.target.avator}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/name"
android:layout_width="80dp"
android:layout_height="40dp"
android:gravity="center"
android:text="@{user.target.name??`zhangsan`}"
android:textSize="14sp"
app:layout_constraintLeft_toRightOf="@id/avator"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/age"
android:layout_width="80dp"
android:layout_height="40dp"
android:gravity="center"
android:text="@{user.target.age}"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="@id/avator"
app:layout_constraintLeft_toRightOf="@id/avator"
app:layout_constraintTop_toBottomOf="@id/name" />
</android.support.constraint.ConstraintLayout>
</layout>
//studentItem
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="student"
type="com.google.simple.model.wrapper.StudentItemWrapper" />
</data>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{student.clickParent}"
android:padding="9dp">
<ImageView
android:id="@+id/student_avator"
android:layout_width="120dp"
android:layout_height="120dp"
android:onClick="@{student.clickImage}"
app:avator="@{student.target.avator}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/student_name"
android:layout_width="80dp"
android:layout_height="40dp"
android:gravity="center"
android:text="@{student.target.name??`zhangsan`}"
android:textColor="#f00"
android:textSize="14sp"
app:layout_constraintLeft_toRightOf="@id/student_avator"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/student_age"
android:layout_width="80dp"
android:layout_height="40dp"
android:gravity="center"
android:text="@{student.target.age}"
android:textColor="#f00"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="@id/student_avator"
app:layout_constraintLeft_toRightOf="@id/student_avator"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/student_name" />
</android.support.constraint.ConstraintLayout>
</layout>
这样bean的复用就解决了
具体操作与上一篇类似(注意两种方案天生支持多类型) 这里有个代码地址 simple
思考
虽然我们把adapter和viewholder省掉了 但是我们多了一个LayoutWrapper,LayoutWrapper牵扯到具体的ui交互,也就是说不能通过注解来解决(尽管我们可以自定义注解将接口的代码省去,但是并不能解决根本问题),那么这么做到底值不值得呢?我个人觉得 应该是值得的,首先adapter和Viewholder是两个类吧,我们用一个wrapper代替,其次wrapper配合databind+google新架构 数据刷新、设置等操作不用手写了,这样也就少写很多代码了。以上只是个人看法,如有建议欢迎评论 多谢指教 (0.0)