[Basics of Android Development] The use of ViewModel in Fragment

1. Brief description

  • Description: When the Activity/Fragment data processing volume is large, there will be a huge amount of data in an XXActivity.java/XXFragment.java. The main function of these two should be to connect UI controls and render data, so this violates the "single responsibility" principle, so the data should be stored and read separately. For this reason, Android officially provides developers with the ViewModel class.
  • Difficulty: Beginner
  • Knowledge points:
  • 1. Understand the concept of data storage address in Java (logical and physical)
  • 2. Understand the observer pattern in software architecture
  • 3. Use of Adapter
  • 4. Get to know ViewModel

2. Create ViewModel

In order to keep the article concise, here we directly use the Bottom Navigation Activity configured by Android studio.

Insert image description here

After creating the project, you can see the configured ViewModel

Insert image description here

3. Understand LiveData

LiveData is still difficult to understand for beginners, so it’s good to know how to use it here.
Main function: Notify the Observe class to pass the latest data to the rendering method (similar to the two-way binding v-model in Vue). The entity class monitors data changes through postValue (this), which is called in the software architecture For observer mode .

ViewModel observer pattern

4. Use ViewModel

1. Single data

For example, create the initial look

Insert image description here

This is very simple, just skip it and just follow this template.

Insert image description here

2. Entity data

Obviously, any Android app in the App Store cannot just render a single piece of data. It must involve entity data (server sends json -> Android receives json -> json to entity)

(1) Create LiveData entity

Here we take the product entity class as an example (this is the entity class of the blog shopping cart function module that will be written later)

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)Write ViewModel

Here we take HomeFragment and HomeViewModel in the template as an example

  • 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

Before studying this section, you need to study the List adapter among the three common adapters (Adapter) in the column [Basics of Android Development]. You can also copy the adapter code in the attachment

Insert image description here

    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);
    }
  • Effect
    Insert image description here

5. Accessories

1. Adapter UI interface design code

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. Adapter data binding code

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();
    }

}

Guess you like

Origin blog.csdn.net/weixin_48916759/article/details/130633430