在Android中使用RecyclerView - Part2

概述

在Android中使用RecyclerView - Part1中,我们学习了如何创建一个自定义的RecyclerView,接下来我们会将RecyclerViewViewModelLiveData结合起来,对Part1的代码进行重构,实现添加产品的功能,最终的运行效果如下:

运行效果

应用架构

下图是Google推荐的应用架构,它强调了应用中的各模块应彼此独立。

推荐应用架构

  • Activity/Fragment : 只放UI相关代码
  • ViewModel:存放操作数据逻辑的代码,将数据放到LiveData中,当LiveData数据发生变化时,会通知UI进行 更新
  • Repository:仓库类,控制数据的来源。例如:数据可能来自本地数据库,也可能来自服务器
  • Model:自本地数据库模型,该类中会放增删改查本地数据库的逻辑
  • Remote Data Source:服务器数据模型,该类中会放增删改查服务器数据的逻辑。我们可以利用Retrofit第三方库,完成网络请求的相关操作

我们按照Google推荐的应用架构,来设计Demo的架构,如下图:

Demo的应用架构

  • MainActivity:存放UI相关逻辑
  • ProductViewModelViewModel类,存放数据操作逻辑
  • ProductRepositoryProduct仓库类
  • FakeDataSource:创建一个"假的"数据来源类

Java代码改造

创建FakeDataSource

首先,创建一个FakeDataSource类,用作操作Product的数据。这个类中主要有4个方法:

  • public void add(Product product) :添加产品
  • public void delete(int index):删除产品
  • public void modify(int index, Product product):更新产品
  • public MutableLiveData> getList():获取产品列表

每次有数据更新时,会通过listMutableLiveData.setValue(list);把值设置到LiveData中,这样在MainAtivity中就可以通过LiveData监听到list的变化

public class FakeDataSource {
    private MutableLiveData> listMutableLiveData;
    private List list;

    public FakeDataSource() {
        listMutableLiveData = new MutableLiveData<>();
        list = new ArrayList<>();
        listMutableLiveData.setValue(list);
    }

    public void add(Product product) {
        list.add(product);
        listMutableLiveData.setValue(list);
    }

    public void delete(int index) {
        if (list.size() < index) {
            return;
        }
        list.remove(index);
        listMutableLiveData.setValue(list);
    }

    public void modify(int index, Product product) {
        if (list.size() < index) {
            return;
        }
        list.set(index, product);
        listMutableLiveData.setValue(list);
    }

    public MutableLiveData> getList() {
        return listMutableLiveData;
    }
}

创建ProductRepository

创建仓库类ProductRepository,这个类会调用到FakeDataSource中的方法

public class ProductRepository {
    private FakeDataSource fakeDataSource;

    public ProductRepository() {
        fakeDataSource = new FakeDataSource();
    }

    public void add(Product product) {
        fakeDataSource.add(product);
    }

    public void delete(int index) {
        fakeDataSource.delete(index);
    }

    public void modify(int index, Product product) {
        fakeDataSource.modify(index, product);
    }

    public MutableLiveData> getList() {
        return fakeDataSource.getList();
    }
}

创建ProductViewModel

创建ViewModelProductViewModel,这个类会调用ProductRepository中的方法

public class ProductViewModel extends ViewModel {
    private ProductRepository repository;

    public ProductViewModel() {
        repository = new ProductRepository();
    }

    public void add(Product product) {
        repository.add(product);
    }

    public void delete(int index) {
        repository.delete(index);
    }

    public void modify(int index, Product product) {
        repository.modify(index, product);
    }

    public MutableLiveData> getList() {
        return repository.getList();
    }
}

修改MyAdapter

1、在MyAdapter中新增ProductViewModel和构造方法。ProductViewModel通过构造方传入到MyAdapter

private ProductViewModel viewModel;

public MyAdapter(ProductViewModel viewModel) {
    this.viewModel = viewModel;
}

2、修改onBindViewHolder,通过ProductViewModel获取list,再从list中获取Product

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
    List list = viewModel.getList().getValue();
    if (list.size() > 0) {
        Product product = list.get(position);
        binding.name.setText(product.getName());
        binding.price.setText(product.getPrice() + "¥");
        binding.index.setText(String.valueOf(position + 1));
    }
}

3、修改getItemCount,通过ProductViewModel获取list的长度,即RecyclerView需要展示的item个数

@Override
public int getItemCount() {
    List list = viewModel.getList().getValue();
    return list.size();
}

修改Main Activity

1、增加private ProductViewModel model;
2、创建ProductViewModel,需要引入依赖implementation "androidx.lifecycle:lifecycle-viewmodel:2.3.0"
3、将ProductViewModel作为参数,传给MyAdapter的构造方法

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;
    private MyAdapter adapter;  
    private ProductViewModel model;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        model = new ViewModelProvider(this).get(ProductViewModel.class);

        binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
        adapter = new MyAdapter(model);
        binding.recyclerView.setAdapter(adapter);
    }
}

在完成前面的代码后,运行效果如下:

运行效果

因为现在没有创建产品,所以列表是空的。接下来,会在主界面增加产品添加的功能

UI界面改造

添加控件

在主界面增加2个EditText和1个Button,用作添加产品

添加控件

对应代码如下:




    

实现添加产品功能

接下来,在MainActivity中设置button的按键监听。按下按键时,去获取EditText的内容,并创建一个Product类,再调用ProductViewModeladd方法,把产品添加进去

public class MainActivity extends AppCompatActivity {
     .... ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
       ... ...

        binding.add.setOnClickListener(view -> {
            if (TextUtils.isEmpty(binding.name.getText())
                    || TextUtils.isEmpty(binding.price.getText())) {
                Toast.makeText(this, "请输入名称和价格", Toast.LENGTH_SHORT).show();
                return;
            }
            String name = binding.name.getText().toString();
            String price = binding.price.getText().toString();

            Product product = new Product();
            product.setName(name);
            product.setPrice(Float.parseFloat(price));

            model.add(product);
        });
    }
}

实现列表更新功能

设置ProductViewModel中的LiveData数据监听,当MutableLiveData>发生变化时,会回调onChanged方法,再通过adapter.notifyDataSetChanged()实现list的更新

public class MainActivity extends AppCompatActivity {
    ... ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ... ...

        model.getList().observe(this, new Observer>() {
            @Override
            public void onChanged(List products) {
                adapter.notifyDataSetChanged();
            }
        });
    }
}

运行效果

所有代码已经编写完成,最终运行效果如下:

运行效果

参考

应用架构指南

完整代码

https://github.com/zhanghuamao/RecyclerViewDemo02

你可能感兴趣的:(在Android中使用RecyclerView - Part2)