Blog of CodeJELLOW’S ENGINEERING NOTES
← 返回文章

Android RecyclerView结合DataBinding和LiveData

Android RecyclerView结合DataBinding和LiveData 记录使用DataBinding实现对拥有RecyclerView组件的页面进行较大程度的解耦的方式。

本文目录 ⌄

    本文目的:记录使用DataBinding实现对拥有RecyclerView组件的页面进行较大程度的解耦的方式。

    RecyclerView数据源:从本地SQLite数据库中使用Room获取一个LiveData并存储在ViewModel中:

    TEXT
    public class StudentViewModel extends AndroidViewModel {
    
        private StudentRepository repository;
        private LiveData<List<Student>> studentsLD;
    
        public StudentViewModel(@NonNull Application application) {
            super(application);
            this.repository=new StudentRepository(application);
            studentsLD=repository.getAllStudentsLive();
        }
    
        public void insert(){
            Student s1=new Student("jack",18);
            Student s2=new Student("rose",17);
            insertStudents(s1,s2);
        }
    
        public void update(){
            Student s1=new Student(3,"jason",20);
            updateStudents(s1);
        }
    
        public void clear(){
            deleteAllStudents();
        }
    
        public void delete(){
            Student s1=new Student(2,"rose",17);
            deleteStudents(s1);
        }
    
    
        private void insertStudents(Student... students){
            repository.insertStudents(students);
        }
    
        private void updateStudents(Student... students){
            repository.updateStudents(students);
        }
    
        private void deleteStudents(Student... students){
            repository.deleteStudents(students);
        }
    
        private void deleteAllStudents(){
            repository.deleteAllStudents();
        }
    
    //  错误!!!
    //    public LiveData<List<Student>> getAllStudentLive(){
    //        return repository.getAllStudentsLive();
    //    }
    
    //   正确
        public LiveData<List<Student>> getStudentsLD() {
            return studentsLD;
        }
    }

    将获取到的LiveData<List<Student>>对象通过DataBinding传给Activity的xml布局中:

    TEXT
    <?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"
        xmlns:tools="http://schemas.android.com/tools">
    
        <data>
            <variable
                name="viewModel"
                type="com.shopkeeper.room2.StudentViewModel" />
        </data>
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".MainActivity">
    
            <Button
                android:id="@+id/button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="60dp"
                android:text="增加"
                android:onClick="@{()->viewModel.insert()}"
                app:layout_constraintBottom_toBottomOf="@+id/button2"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/button2" />
    
            <Button
                android:id="@+id/button2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="60dp"
                android:layout_marginEnd="60dp"
                android:text="删除"
                android:onClick="@{()->viewModel.delete()}"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
    
            <Button
                android:id="@+id/button3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="60dp"
                android:text="修改"
                android:onClick="@{()->viewModel.update()}"
                app:layout_constraintEnd_toEndOf="@+id/button"
                app:layout_constraintStart_toStartOf="@+id/button"
                app:layout_constraintTop_toBottomOf="@+id/button" />
    
            <Button
                android:id="@+id/button4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="清空"
                android:onClick="@{()->viewModel.clear()}"
                app:layout_constraintBottom_toBottomOf="@+id/button3"
                app:layout_constraintEnd_toEndOf="@+id/button2"
                app:layout_constraintStart_toStartOf="@+id/button2"
                app:layout_constraintTop_toTopOf="@+id/button3" />
    
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recycleView"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_marginTop="30dp"
                app:studentBinder="@{viewModel.studentsLD}"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/button3" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>

    此处定义了一个studentBinder的BindingAdapter,用于处理传递过来的数据:

    TEXT
    public class RVAdapter {
    
        @BindingAdapter("studentBinder")
        public static void studentsBindAdapter(RecyclerView recyclerView, List<Student> students){
            StudentAdapter adapter = (StudentAdapter) recyclerView.getAdapter();
            assert adapter != null;
            adapter.setStudents(students);
        }
    }

    由于绑定的是LiveData数据,所以每当列表发生改变时,就会自动执行BindingAdapter中的方法,进而通过RecyclerView的Adapter更新并显示数据(每一个Item也是通过DataBinding来绑定数据的)。Adapter内容:

    TEXT
    public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.StudentViewHolder> {
    
        List<Student> students;
    
        public StudentAdapter(List<Student> students) {
            this.students = students;
        }
    
        @NonNull
        @Override
        public StudentViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            ItemBinding binding= DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),R.layout.item,parent,false);
            return new StudentViewHolder(binding);
        }
    
        @Override
        public void onBindViewHolder(@NonNull StudentViewHolder holder, int position) {
            holder.binding.setStudent(students.get(position));
        }
    
        @Override
        public int getItemCount() {
            return students==null?0:students.size();
        }
    
        static class StudentViewHolder extends RecyclerView.ViewHolder{
            ItemBinding binding;
            public StudentViewHolder(@NonNull ItemBinding binding) {
                super(binding.getRoot());
                this.binding=binding;
            }
        }
    
        public void setStudents(List<Student> students) {
            this.students = students;
            notifyDataSetChanged();
        }
    }

    通过这种写法,在Activity中的代码量就很少了,甚至不需要使用Observer来监听LiveData的数据变化:

    TEXT
    public class MainActivity extends AppCompatActivity {
    
        ActivityMainBinding binding;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding= DataBindingUtil.setContentView(this,R.layout.activity_main);
            StudentViewModel viewModel = new ViewModelProvider(this,
                    new ViewModelProvider.AndroidViewModelFactory(getApplication()))
                    .get(StudentViewModel.class);
            binding.recycleView.setAdapter(new StudentAdapter(viewModel.getStudentsLD().getValue()));
            binding.recycleView.setLayoutManager(new LinearLayoutManager(this));
            binding.setViewModel(viewModel);
            binding.setLifecycleOwner(this);
        }
    }

    效果图:

    图片暂不可用。

    通过 RSS 订阅更新 →