还记得我们进入Listview、GridView都是以一个layout+adapter组合在一起来实现的是吧?那么还记得我们的Adapter的写法么?
在我们的Adapter里提供了一个bindView方法 。
在调用时我们需要在Activity里把layout里的控件元素一个个传给这个Adapter。
在我们的例子里我们的layout里只有两个对象
那么如果我们现在假设需要实现以下这样的界面(笔者正在制作的基于spring cloud2.0微服务+Android MVVM开源商城,我做完后会把前后端都开源出来。mao-sir.com是笔者拥有的实名域名中的一个)。
我们可以看到标记1处有两处图片、5处文字。
再来看标记2处,有一个图片+两个文字。
如果按照我们之前这个Adapter的写法,岂不是要为这两个layout各写2个Adapter吗?那么我们假设在整个app开发过程中有100个不同的layout呢?那岂不是要变成了Adapter泛滥了吗?
答案就是:不用这么多Adapter,我们可以使用Databinding来解决大多数问题!
下面我们就来看如何应对这样的场景。
假设我们需要完成以下这样的一个ListView。
我们可以看到这样的一个ListView有两个元素构成了它的基本的每一行的Layout。
我们直接来看代码。
package com.mkyuan.android.demo.mvvm;
import android.widget.ImageView;
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import androidx.databinding.BindingAdapter;
import com.bumptech.glide.Glide;
public class User extends BaseObservable {
public User(String name, int header) {
this.name = name;
this.header = header;
}
private String name = "";
private int header;
@Bindable
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
@Bindable
public int getHeader() {
return header;
}
public void setHeader(int header) {
this.header = header;
notifyPropertyChanged(BR.header);
}
//自定义属性 headUrl 是自定义的,在xml的imageView中引用
@BindingAdapter("headId")
public static void getImage(ImageView view, int headerId) {
Glide.with(view.getContext()).load(headerId).into(view);
}
}
我们可以看到在这个JavaBean里我们依然使用了Glid工具把图片显示到界面上。
dependencies {
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
在这个layout里我们使用了databinding。
package com.mkyuan.android.demo.mvvm;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import java.util.List;
public class MyListAdapter extends BaseAdapter {
private Context context;
private LayoutInflater inflater;
private int layoutId;
private int variableId;
private List list;
public MyListAdapter(Context context, int layoutId, List list, int resId) {
this.context = context;
this.layoutId = layoutId;
this.list = list;
this.variableId = resId;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewDataBinding dataBinding;
if (convertView == null) {
dataBinding = DataBindingUtil.inflate(inflater, layoutId, parent, false);
} else {
dataBinding = DataBindingUtil.getBinding(convertView);
}
dataBinding.setVariable(variableId, list.get(position));
return dataBinding.getRoot().getRootView();
}
}
从代码上看,我们可以看出这个Adapter才是一个“级极Adapter”,所有代码里没有一点和控件元素、多少个控件有关的语句。说白了就是关你多少个控件。。。只要你把layout传进去都可以dataBinding起来。因此这才是一个通用的Adapter,如果没有什么特殊的情况这个Adapter在我们的项目里往往承担着超过90%左右的界面显示的那些活。
package com.mkyuan.android.demo.mvvm;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "DemoMVVMList";
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
List list = new ArrayList();
list.add(new User("张三", R.drawable.icon_1_128));
list.add(new User("李四", R.drawable.icon_2_128));
list.add(new User("王五", R.drawable.icon_3_128));
list.add(new User("赵六", R.drawable.icon_4_128));
list.add(new User("孙七", R.drawable.icon_5_128));
list.add(new User("周八", R.drawable.icon_6_128));
list.add(new User("吴九", R.drawable.icon_7_128));
MyListAdapter adapter = new MyListAdapter(MainActivity.this,
R.layout.list_items, list,
BR.user);
listView.setAdapter(adapter);
}
}
然后运行起来就得到了我们需要的效果
不妨自己动一下手吧。