Realm 怎么与 RecyclerView 配合使用
Realm 官方有介绍 RealmBaseAdapter with ListView 以及 RealmRecyclerViewAdapter with RecyclerView 的使用.
不过其实 Realm 是可以配合普通的 RecyclerView.Adapter 使用的, 关键在于大家可能不太能理解把一个 RealmList<T>
或者 RealmResults<T>
传到 Adapter 里, 怎么当成 List<T>
处理呢?
其实也没有想象中那么复杂, 但有四个需要注意的点, 我在下面的示例代码中标注了:
// MainActivity.class
public class MainActivity {
// ...
// 假设有一个叫 School.class 的 Javabean, 它有两个成员:
// 成员1: 作为主键的 long 类型的 id
// 成员2: 作为一对多对象的 RealmList<Student> studentList
private void showRecyclerView() {
Realm realm = Realm.getDefaultInstance();
// 下面我们展示的是获取一个实例化的 school
School school = realm.where(School.class).findFirst();
// ps: 获取全部使用的是 findAll() 方法:
// RealmResults<School> schools = realm.where(School.class).findAll();
// [注意 1] 获取一个 studentList
RealmList<Student> studentList = school.getStudentList();
// 实例化一个适配器
MyAdapter adapter = new MyAdapter(studentList);
// 然后 recycler 装载这个适配器, 就能显示了
recycler.setAdapter(adapter);
// 关于适配器的内容, 请往下看 MyAdaptor.class
}
}
// MyAdapter.class
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
// [注意 2] 这里一定要赋值为 new ArrayList<>()
private List<Student> studentList = new ArrayList<>();
// 构造器
// [注意 3] 构造器的参数类型是 List<T>, 而不是 RealmList<T>
// 因为 RealmList 继承于 List<T>, 所以可以这样做 (就好比 TextView 继承于 View, 这里我们参数用的是 "View")
public MyAdapter(List<Student> studentList) {
// [注意 4] 错误的写法:
// this.studentList = studentList;
// 正确的写法:
this.studentList.addAll(studentList);
// 为什么要用 addAll() 而不是等号呢?
// 因为等号是对同一内存地址的引用, addAll() 才是获得一个副本
// 在加载列表视图 (onBindView) 的时候大家可能看不出区别, 因为无论是用 addAll() 还是等号, 都能正常加载;
// 但是当我们对列表进行增删操作时, 后者就会报错了, 因为 Realm 不允许我们直接对着 Pointer 进行操作
// 比如下面写的 addItem(), 就是一个会引起错误的地方. 因此这里一定要用 addAll() 赋值才能避免问题
}
// addItem
public void addItem(int position, Student student) {
studentList.add(position, student);
notifyItemInserted(position); // notify... 是自带的方法
}
/*public void removeItem(int position) {
studentList.remove(position);
notifyItemRemoved(position);
}*/
// Normally overriding operations...
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// 假设 Student.class 有两个成员: 学生的姓名和性别
holder.studentName.setText(studentList.get(position).getStudentName());
holder.studentGender.setText(studentList.get(position).getStudentGender());
}
@Override
public int getItemCount() {
return studentList.size();
}
// ViewHolder constructor
static class ViewHolder extends RecyclerView.ViewHolder {
...
}
}