【Android开发基础】Fragment(碎片)中ViewModel的使用

一、简述

  • 描述:当Activity / Fragment数据处理量大时,一个XXActivity.java / XXFragment.java里就会有庞大的数据量。而这两者的主要作用应该是起到连接UI控件、渲染数据的作用,所以这就违背“单一负责”原则,那么数据就应该单独进行存放以及读取。为此Android官方就为开发者提供了ViewModel类。
  • 难度:初级
  • 知识点:
  • 1、了解Java中数据存储地址的概念(逻辑 and 物理)
  • 2、了解软件体系结构里的观察者模式
  • 3、适配器(Adapter)的使用
  • 4、认识ViewModel

二、创建ViewModel

为了使文章简洁,这里就直接使用Android studio配置好了的Bottom Navigation Activity

在这里插入图片描述

创建好工程后,就可以看到已经配置好了的ViewModel

在这里插入图片描述

三、了解LiveData

LiveData对于初学者而言,还是比较难以理解,这里会用就好了。
主要作用:通知Observe类将最新数据传递给渲染方法(和Vue里的双向绑定v-model有异曲同工之妙),实体类里通过postValue(this)监听数据变化,这在软件体系结构里被称为观察者模式

ViewModel观察者模式

四、使用ViewModel

1、单体数据

如,创建初始的样子

在这里插入图片描述

这个很简单,直接跳过,平常就可以按照这个模板来。

在这里插入图片描述

2、实体类数据

很显然,任何在应用商店的Android app,不可能只是对单一数据进行渲染。必然牵扯到实体类数据(服务器发送json -> Android接收json -> json转实体)

(1)创建LiveData实体

这里以商品实体类为例(这是后面将写的博客购物车功能模块的实体类)

import androidx.lifecycle.LiveData;

public class Shop extends LiveData<Shop> {
    
    

    int id;
    String image;
    String name;
    int price;
    String bus;
    float dis;
    String time;
    String des;

    public int getId() {
    
    
        return id;
    }

    public String getImage() {
    
    
        return image;
    }

    public String getName() {
    
    
        return name;
    }

    public int getPrice() {
    
    
        return price;
    }

    public String getBus() {
    
    
        return bus;
    }

    public float getDis() {
    
    
        return dis;
    }

    public String getTime() {
    
    
        return time;
    }

    public String getDes() {
    
    
        return des;
    }

    public void setId(int id) {
    
    
        this.id = id;
        postValue(this);
    }

    public void setImage(String image) {
    
    
        this.image = image;
        postValue(this);
    }

    public void setName(String name) {
    
    
        this.name = name;
        postValue(this);
    }

    public void setPrice(int price) {
    
    
        this.price = price;
        postValue(this);
    }

    public void setBus(String bus) {
    
    
        this.bus = bus;
        postValue(this);
    }

    public void setDis(float dis) {
    
    
        this.dis = dis;
        postValue(this);
    }

    public void setTime(String time) {
    
    
        this.time = time;
        postValue(this);
    }

    public void setDes(String des) {
    
    
        this.des = des;
        postValue(this);
    }
}

(2)编写ViewModel

这里以模板里的HomeFragment和HomeViewModel为例

  • HomeViewModel.java
import androidx.lifecycle.ViewModel;

import com.hngy.xpq.shoppingcartmodule.bean.Shop;

import java.util.ArrayList;
import java.util.List;

public class HomeViewModel extends ViewModel {
    
    

    private Shop shop = new Shop();
    private List<Shop> ls;
    
    public List<Shop> getListShop() {
    
    
        ls = new ArrayList<>();
        // 这里是获取数据,一般有三种方式
        // 1、手动填充数据(测试)
        // 2、HTTP获取服务器数据
        // 3、本地数据库存储的数据
        for (int i = 0; i < 5;i++) {
    
    
            Shop s = new Shop();
            s.setName("name" + i);
            s.setPrice(10 + i);
            s.setBus("商家" + i);
            s.setDis(Float.valueOf("2.55") + i);
            s.setTime("周" + i);
            s.setDes("无");
            ls.add(s);
        }
        // ------------end---------- //
        return ls;
    }

    // 测试数据的改变,会不会影响视图显示的数据
    public void xg() {
    
    
        // 修改数据(不通过setText方法)
        // 需要明白 Java数据地址原理
        ls.get(1).setName("ViewModel绑定数据修改!");
    }
}
  • HomeFragment.java

学习此节前,需要先学习栏目【Android开发基础】三种常见的适配器(Adapter)中List适配器。也可以复制附件中关于适配器的代码

在这里插入图片描述

    private RecyclerView listShop;
    private List<Shop> shopList;
    
	private void init(View root) {
    
    
        shopList = homeViewModel.getListShop();
        listShop = root.findViewById(R.id.listShop);
        getListAdapter();    // 数据渲染
        homeViewModel.xg();  // 修改数据
    }

    // List适配器
    private void getListAdapter() {
    
    
        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(1,StaggeredGridLayoutManager.VERTICAL);
        listShop.setLayoutManager(layoutManager);
        ListAdapter adapter = new ListAdapter(shopList);
        listShop.setAdapter(adapter);
    }
  • 效果
    在这里插入图片描述

五、附件

1、适配器UI界面设计代码

item_list.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="15dp"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/homeImage"
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:background="@drawable/ic_launcher_background"/>

    <TextView
        android:id="@+id/homeName"
        android:layout_width="match_parent"
        android:layout_height="25dp"
        android:layout_marginLeft="18dp"
        android:layout_toEndOf="@+id/homeImage"
        android:textSize="50px"/>

    <TextView
        android:id="@+id/homeTime"
        android:layout_width="150dp"
        android:layout_height="25dp"
        android:layout_below="@+id/homeName"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="18dp"
        android:layout_marginTop="5dp"
        android:layout_toEndOf="@+id/homeImage"
        android:textSize="50px" />

    <TextView
        android:id="@+id/homeDes"
        android:layout_width="150dp"
        android:layout_height="25dp"
        android:layout_below="@+id/homeTime"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="18dp"
        android:layout_marginTop="5dp"
        android:layout_toEndOf="@+id/homeImage"
        android:textSize="50px" />

    <TextView
        android:id="@+id/homePrice"
        android:layout_width="150dp"
        android:layout_height="25dp"
        android:layout_below="@+id/homeDes"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="18dp"
        android:layout_marginTop="5dp"
        android:layout_toEndOf="@+id/homeImage"
        android:textSize="50px" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:gravity="bottom|right"
        android:paddingBottom="20dp">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="加入"/>

    </LinearLayout>

</RelativeLayout>

2、适配器数据绑定代码

ListAdapter.java

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.hngy.xpq.shoppingcartmodule.R;
import com.hngy.xpq.shoppingcartmodule.bean.Shop;

import java.util.List;

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {
    
    

    private List<Shop> listData;

    static class ViewHolder extends RecyclerView.ViewHolder {
    
    

        View fileView;
        ImageView image;
        TextView name, price, dis, time, des;

        public ViewHolder(View itemView) {
    
    
            super(itemView);
            fileView = itemView;
            name = itemView.findViewById(R.id.homeName);
            price = itemView.findViewById(R.id.homePrice);
            time = itemView.findViewById(R.id.homeTime);
            des = itemView.findViewById(R.id.homeDes);
        }
    }

    // 获取到数据
    public ListAdapter(List<Shop> list) {
    
    
        this.listData = list;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, int viewType) {
    
    
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list,parent,false);
        final ViewHolder holder = new ViewHolder(view);

        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    
    
        // 数据绑定
        final Shop s = listData.get(position);
        holder.name.setText(s.getName());
        holder.price.setText("¥" + s.getPrice());
        holder.time.setText(s.getTime());
        holder.des.setText(s.getDes());
    }

    @Override
    public int getItemCount() {
    
    
        return listData.size();
    }

}

猜你喜欢

转载自blog.csdn.net/weixin_48916759/article/details/130633430