databinding 基本使用,点击事件,自定义属性,recyclerview使用
页面是一个RecyclerView,Item为图片 + 姓名 + 年龄
配置
android {
...
dataBinding {
enabled true
}
}
dependencies {
...
implementation 'com.github.bumptech.glide:glide:4.10.0'
implementation 'com.android.support:recyclerview-v7:29.0.2'
}
java版本
xml布局文件,主页面
activity_main_java
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="person"
type="com.tongjin.mvvm_kotlin.java.PersonsViewModel" />
</data>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</layout>
item布局,item_java
<?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="person"
type="com.tongjin.mvvm_kotlin.java.PersonViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{person.itemClick}"
android:padding="10dp">
<ImageView
android:layout_width="90dp"
android:layout_height="120dp"
android:scaleType="centerCrop"
app:image="@{person.photo}"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="@{person.name}"
android:textSize="18sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:textSize="18sp"
android:text="@{String.valueOf(person.age)}"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</layout>
MainActivityJava
public class MainActivityJava extends AppCompatActivity {
private Handler handler = new Handler();
private PersonsViewModel persons;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainJavaBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main_java);
persons = new PersonsViewModel();
binding.setPerson(persons);
CommonRecyclerViewAdapter<PersonViewModel, ItemJavaBinding> adapter = new CommonRecyclerViewAdapter<>(this, R.layout.item_java, BR.person, persons.personsList);
binding.list.setLayoutManager(new LinearLayoutManager(this));
binding.list.setAdapter(adapter);
handler.postDelayed(new Runnable() {
@Override
public void run() {
persons.personsList.add(new PersonViewModel("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1570799520739&di=57dabff1116da2ce2e860f751063495f&imgtype=0&src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Falbum%2Ffee6ff8f524a42eabb75f1538d7312cfdd246b9e.jpg", "王五", 100));
}
}, 3000);
}
}
PersonsViewModel
public class PersonsViewModel {
public ObservableList<PersonViewModel> personsList = new ObservableArrayList<>();
public PersonsViewModel() {
personsList.add(new PersonViewModel("", "aa", 33));
}
}
PersonViewModel
public class PersonViewModel {
public ObservableField<String> photo = new ObservableField<>();
public ObservableField<String> name = new ObservableField<>();
public ObservableInt age = new ObservableInt();
public PersonViewModel(String photo, String name, int age) {
this.photo.set(photo);
this.name.set(name);
this.age.set(age);
}
// 可以加上命名空间:app:image,但xml中只可以用app:image
@BindingAdapter("image")
public static void bindImage(ImageView imageView, String photo) {
Glide.with(imageView.getContext()).load(photo).into(imageView);
}
public void itemClick(View view) {
Toast.makeText(view.getContext(), name.get(), Toast.LENGTH_SHORT).show();
}
}
通用的Adapter
public class CommonRecyclerViewAdapter<M, B extends ViewDataBinding> extends RecyclerView.Adapter {
private Context context;
private ObservableList<M> items;
private int layoutId;
private int resId;
protected ListChangedCallback itemsChangeCallback;
public CommonRecyclerViewAdapter(Context context, int layoutId, int resId, ObservableList<M> list) {
this.context = context;
this.layoutId = layoutId;
this.resId = resId;
this.items = list;
this.itemsChangeCallback = new ListChangedCallback();
}
public ObservableList<M> getItems() {
return items;
}
public class BaseBindingViewHolder extends RecyclerView.ViewHolder {
public BaseBindingViewHolder(View itemView) {
super(itemView);
}
}
@Override
public int getItemCount() {
return this.items.size();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
B binding = DataBindingUtil.inflate(LayoutInflater.from(this.context), layoutId, parent, false);
return new BaseBindingViewHolder(binding.getRoot());
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
B binding = DataBindingUtil.getBinding(holder.itemView);
if (binding != null) {
binding.setVariable(resId, this.items.get(position));
}
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
this.items.addOnListChangedCallback(itemsChangeCallback);
}
@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
super.onDetachedFromRecyclerView(recyclerView);
this.items.removeOnListChangedCallback(itemsChangeCallback);
}
//region 处理数据集变化
protected void onChanged(ObservableArrayList<M> newItems) {
resetItems(newItems);
notifyDataSetChanged();
}
protected void onItemRangeChanged(ObservableArrayList<M> newItems, int positionStart, int itemCount) {
resetItems(newItems);
notifyItemRangeChanged(positionStart, itemCount);
}
protected void onItemRangeInserted(ObservableArrayList<M> newItems, int positionStart, int itemCount) {
resetItems(newItems);
notifyItemRangeInserted(positionStart, itemCount);
}
protected void onItemRangeMoved(ObservableArrayList<M> newItems) {
resetItems(newItems);
notifyDataSetChanged();
}
protected void onItemRangeRemoved(ObservableArrayList<M> newItems, int positionStart, int itemCount) {
resetItems(newItems);
notifyItemRangeRemoved(positionStart, itemCount);
}
protected void resetItems(ObservableArrayList<M> newItems) {
this.items = newItems;
}
private class ListChangedCallback extends ObservableArrayList.OnListChangedCallback<ObservableArrayList<M>> {
@Override
public void onChanged(ObservableArrayList<M> newItems) {
CommonRecyclerViewAdapter.this.onChanged(newItems);
}
@Override
public void onItemRangeChanged(ObservableArrayList<M> newItems, int i, int i1) {
CommonRecyclerViewAdapter.this.onItemRangeChanged(newItems, i, i1);
}
@Override
public void onItemRangeInserted(ObservableArrayList<M> newItems, int i, int i1) {
CommonRecyclerViewAdapter.this.onItemRangeInserted(newItems, i, i1);
}
@Override
public void onItemRangeMoved(ObservableArrayList<M> newItems, int i, int i1, int i2) {
CommonRecyclerViewAdapter.this.onItemRangeMoved(newItems);
}
@Override
public void onItemRangeRemoved(ObservableArrayList<M> sender, int positionStart, int itemCount) {
CommonRecyclerViewAdapter.this.onItemRangeRemoved(sender, positionStart, itemCount);
}
}
}
kotlin
增加配置
apply plugin: 'kotlin-kapt'
kapt {
generateStubs = true
}
xml布局,与java的一样
activity_main_kotlin
<?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="persons"
type="com.tongjin.mvvm_kotlin.kotlin.PersonsViewModel" />
</data>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</layout>
item_kotlin
<?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="person_kotlin"
type="com.tongjin.mvvm_kotlin.kotlin.PersonViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{person_kotlin.itemClick}"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<ImageView
android:layout_width="90dp"
android:layout_height="120dp"
android:scaleType="centerCrop"
app:image="@{person_kotlin.photo}"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="@{person_kotlin.name}"
android:textSize="18sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:textSize="18sp"
android:text="@{String.valueOf(person_kotlin.age)}"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</layout>
MainActivityKotlin
class MainActivityKotlin : AppCompatActivity() {
private val handler = Handler()
private lateinit var persons: PersonsViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityMainKotlinBinding>(this, R.layout.activity_main_kotlin)
persons = PersonsViewModel()
binding.persons = persons
val adapter = CommonRecyclerViewAdapter<PersonViewModel, ItemKotlinBinding>(this@MainActivityKotlin, R.layout.item_kotlin, BR.person_kotlin, persons.persons)
binding.list.layoutManager = LinearLayoutManager(this)
binding.list.adapter = adapter
handler.postDelayed({
persons.persons.add(PersonViewModel(
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1570799520739&di=57dabff1116da2ce2e860f751063495f&imgtype=0&src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Falbum%2Ffee6ff8f524a42eabb75f1538d7312cfdd246b9e.jpg",
"赵六",
300
)
)
}, 3000)
}
}
PersonsViewModel
class PersonsViewModel {
val persons = ObservableArrayList<PersonViewModel>()
init {
persons.add(PersonViewModel("", "tt", 50))
}
}
PersonViewModel
class PersonViewModel (photo: String,
name: String,
age: Int) {
val photo = ObservableField<String>()
val name = ObservableField<String>()
val age = ObservableInt()
init {
this.photo.set(photo)
this.name.set(name)
this.age.set(age)
}
companion object {
@BindingAdapter("image")
@JvmStatic
fun bindImage(imageView: ImageView, photo: String) {
Glide.with(imageView.context).load(photo).into(imageView)
}
}
fun itemClick(view: View) {
Toast.makeText(view.context, name.get(), Toast.LENGTH_SHORT).show()
}
}