IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 组件化之路 - LiveData + ViewModel一知半解 -> 正文阅读

[移动开发]组件化之路 - LiveData + ViewModel一知半解

减法、减法、继续减法,之前记录了一半,最近抽时间再补全一下,仅为个人见解~

Android Architecture Components 架构组件

因为一直处于小厂的舒适区中,所以除了自我驱动外,一般根本不会接触到近几年的新技术,不过该庆幸的是 “吾虽未齐头奋进,但从未落地不前” ~

近几年Jetpack组件库被广泛使用,除去Kotlin的compose等相关组件外,我们首先应该掌握的还是可兼容Java Lifecycle、LiveData、ViewModel 组件套 ~

基本认知

其实在学习ViewModel组件前,最好是掌握了Lifecycle和LiveData组件,因为在ViewModel中看到了这俩个组件的影子!

每个人的学习方式有所不同,有的喜欢看视频,有的喜欢看blog,有的喜欢看源码,但是根据常规顺序学一样知识的时候,最先看的应该是 官方文档 - LiveData官方文档 - ViewModel

我不太清楚别人是如何理解 LiveData、ViewModel 的,我也不知道这么理解对不对 ?

  • ViewModel 官网介绍:ViewModel类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。
  • ViewModel 自我理解:保留数据、视图的意外丢失,支持Activity和依赖该Activity的Fragment共享数据源
  • LiveData 自我理解:可被观察的数据持有类
  • LiveData+LiveData 自我理解:ViewModel分解为View、Model,主要通过数据来驱动视图,可实时监听数据变化,内部应该采用了观察者模式,这里主要是LiveData特性;涉及到生命周期的范围,一般都用到了Lifecycle

基础实现

build.gradle 引入依赖

    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:1.1.0"
// alternatively, just ViewModel
//    implementation "android.arch.lifecycle:viewmodel:1.1.0"
// alternatively, just LiveData
//    implementation "android.arch.lifecycle:livedata:1.1.0"
官网示例

注意:此示例为官网中ViewModel的使用示例,尽可借鉴,有个大概印象就好

ViewModel

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<User>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}

Activity

public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        // Create a ViewModel the first time the system calls an activity's onCreate() method.
        // Re-created activities receive the same MyViewModel instance created by the first activity.

        MyViewModel model = new ViewModelProvider(this).get(MyViewModel.class);
        model.getUsers().observe(this, users -> {
            // update UI
        });
    }
}

Fragment

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> getSelected() {
        return selected;
    }
}

public class ListFragment extends Fragment {
    private SharedViewModel model;

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends Fragment {

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        SharedViewModel model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
        model.getSelected().observe(getViewLifecycleOwner(), item -> {
           // Update the UI.
        });
    }
}

自我演练

既然都说是ViewModel了,肯定是以model为单元进行演练的,但是最后我也加入了类似LiveData单字符串的调用方式 ~

TestModel

这个很常见,可以理解为model、bean这样的实体类,没什么特殊的

package com.example.livedata;

/**
 * @author MrLiu
 * @date 2021/12/21
 * desc
 */
public class TestModel {
    public TestModel(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public TestModel() {
        super();
    }

    public String name;
    public int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

TestViewModel

这个类比较关键,是ViewModel组件实现的主体类;关于以下俩种实现方式的最终效果是一致的,主要区别在于LiveData和MutableLiveData更新数据时的使用方式,关于具体区别看我上面提到的 LiveData Blog 就好~

实现方式 1:根据官方示例 获取ViewModel时,返回的是LiveData,导致只能通过类内方法进行设值,个人不建议这么使用,虽然实现了出口统一,但是使用起来有点麻烦;不过不能一棒子打死,根据自己场景选取实现方式吧~

package com.example.livedata;

import android.util.Log;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

/**
 * @author MrLiu
 * @date 2021/12/21
 * desc 类似官方的实现方式
 */
public class TestViewModel extends ViewModel {
    private MutableLiveData<TestModel> liveData;
    
    public LiveData<TestModel> getTestViewModel() {
        if (liveData == null) {
            liveData = new MutableLiveData<TestModel>();
        }
        return liveData;
    }
    
    /**
    * 修改数据源
    */
     public void setTestViewModel(TestModel testModel) {
        liveData.postValue(testModel);
    }
    
    /**
     * 可写可不写,主要看需求,用于监听依赖组件的生命周期
     * 由于屏幕旋转导致的Activity重建,该方法不会被调用;
     * 只有ViewModel已经没有任何Activity与之有关联,系统则会调用该方法,你可以在此清理资源
     */
    @Override
    protected void onCleared() {
        super.onCleared();
        Log.e("tag","只有ViewModel已经没有任何Activity与之有关联,系统则会调用该方法,你可以在此清理资源");
    }
}:

MainActivity

package com.example.livedata;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;


public class MainActivity extends AppCompatActivity {

    private TestViewModel testViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView mName = findViewById(R.id.tv_test);

        testViewModel = ViewModelProviders.of(this).get(TestViewModel.class);
        //接收源,当数据发生改变就会被及时监听到
        testViewModel.getTestViewModel().observe(this, new Observer<TestModel>() {
            @Override
            public void onChanged(TestModel testModel) {
                mName.setText("姓名:" + testModel.getName() + " - 年龄:" + testModel.age);
            }
        });

        //发送源,改变数据的地方,此处只是示例而已
        mName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testViewModel.setTestViewModel(new TestModel("吾名:Live",19));
            }
        });
    }
}

实现方式 2根据对LiveData的掌握,我将获取ViewModel的返回类换MutableLiveData, 主要为了方便我自己的灵活调用> <

package com.example.livedata;

import android.util.Log;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

/**
 * @author MrLiu
 * @date 2021/12/21
 * desc 只更改获取ViewModel的返回类型
 */
public class TestViewModel extends ViewModel {
    private MutableLiveData<TestModel> mutableLiveData;

    public MutableLiveData<TestModel> getTestViewModel_Mutable() {
        if (mutableLiveData == null) {
            mutableLiveData = new MutableLiveData<TestModel>();
        }
        return mutableLiveData;
    }

    /**
     * 由于屏幕旋转导致的Activity重建,该方法不会被调用
     * 只有ViewModel已经没有任何Activity与之有关联,系统则会调用该方法,你可以在此清理资源
     */
    @Override
    protected void onCleared() {
        super.onCleared();
        Log.e("tag","只有ViewModel已经没有任何Activity与之有关联,系统则会调用该方法,你可以在此清理资源");
    }
}

MainActivity

package com.example.livedata;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;


public class MainActivity extends AppCompatActivity {

    private TestViewModel testViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView mName = findViewById(R.id.tv_test);

        testViewModel = ViewModelProviders.of(this).get(TestViewModel.class);
        //接收源,当数据发生改变就会被及时监听到
        testViewModel.getTestViewModel_Mutable().observe(this, new Observer<TestModel>() {
            @Override
            public void onChanged(TestModel testModel) {
                mName.setText("姓名:" + testModel.getName() + " - 年龄:" + testModel.age);
            }
        });

        //发送源,改变数据的地方,此处只是示例而已
        mName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testViewModel.getTestViewModel_Mutable().postValue(new TestModel("吾名:Live",19));
            }
        });
    }
}
单串演练

上方主要是关于一个model的监听,这里就是仅观察一个字符串的案例,闲的没事儿尝试后记录一下,和LiveData的基本功能有点一样 ~

TestViewModel

package com.example.livedata;

import android.util.Log;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

/**
 * @author MrLiu
 * @date 2021/12/21
 * desc
 */
public class TestViewModel extends ViewModel {
    private MutableLiveData<String> stringMutableLiveData;

    MutableLiveData<String> getAlone() {
        if (stringMutableLiveData == null) {
            stringMutableLiveData = new MutableLiveData<>();
        }
        return stringMutableLiveData;
    }

    /**
     * 由于屏幕旋转导致的Activity重建,该方法不会被调用
     * 只有ViewModel已经没有任何Activity与之有关联,系统则会调用该方法,你可以在此清理资源
     */
    @Override
    protected void onCleared() {
        super.onCleared();
        Log.e("tag","只有ViewModel已经没有任何Activity与之有关联,系统则会调用该方法,你可以在此清理资源");
    }
}

MainActivity

package com.example.livedata;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;


public class MainActivity extends AppCompatActivity {

    private TestViewModel testViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView mName = findViewById(R.id.tv_alone);

        testViewModel = ViewModelProviders.of(this).get(TestViewModel.class);
        //接收源,当数据发生改变就会被及时监听到
        testViewModel.getAlone().observe(this, new Observer<String>() {
            @Override
            public void onChanged(String data) {
                mAlone.setText(data);
            }
        });

        //发送源,改变数据的地方,此处只是示例而已
        mAlone.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testViewModel.getAlone().postValue("小小笑话可笑可笑");
            }
        });
    }
}

完整Demo

TestModel

package com.example.livedata;

/**
 * @author MrLiu
 * @date 2021/12/21
 * desc
 */
public class TestModel {
    public TestModel(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public TestModel() {
        super();
    }

    public String name;
    public int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

TestViewModel

package com.example.livedata;

import android.util.Log;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

/**
 * @author MrLiu
 * @date 2021/12/21
 * desc
 */
public class TestViewModel extends ViewModel {
    private MutableLiveData<TestModel> liveData;
    private MutableLiveData<TestModel> mutableLiveData;
    private MutableLiveData<String> stringMutableLiveData;

    public LiveData<TestModel> getTestViewModel() {
        if (liveData == null) {
            liveData = new MutableLiveData<TestModel>();
        }
        return liveData;
    }

    public MutableLiveData<TestModel> getTestViewModel_Mutable() {
        if (mutableLiveData == null) {
            mutableLiveData = new MutableLiveData<TestModel>();
        }
        return mutableLiveData;
    }

    public void setTestViewModel(TestModel testModel) {
        liveData.postValue(testModel);
    }

    MutableLiveData<String> getAlone() {
        if (stringMutableLiveData == null) {
            stringMutableLiveData = new MutableLiveData<>();
        }
        return stringMutableLiveData;
    }
    
    /**
     * 由于屏幕旋转导致的Activity重建,该方法不会被调用
     * 只有ViewModel已经没有任何Activity与之有关联,系统则会调用该方法,你可以在此清理资源
     */
    @Override
    protected void onCleared() {
        super.onCleared();
        Log.e("tag", "只有ViewModel已经没有任何Activity与之有关联,系统则会调用该方法,你可以在此清理资源");
    }
}

MainActivity

package com.example.livedata;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;


public class MainActivity extends AppCompatActivity {

    private TestViewModel testViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView mTest = findViewById(R.id.tv_test);
        TextView mAlone = findViewById(R.id.tv_alone);

        testViewModel = ViewModelProviders.of(this).get(TestViewModel.class);
//       数据监听
        testViewModel.getTestViewModel_Mutable().observe(this, new Observer<TestModel>() {
            @Override
            public void onChanged(TestModel testModel) {
                mTest.setText("姓名:" + testModel.getName() + " - 年龄:" + testModel.age);
            }
        });

        testViewModel.getAlone().observe(this, new Observer<String>() {
            @Override
            public void onChanged(String data) {
                mAlone.setText(data);
            }
        });

//      数据发送
        mTest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testViewModel.setTestViewModel(new TestModel("吾名:Live", 19));
            }
        });

        mTest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testViewModel.getTestViewModel_Mutable().postValue(new TestModel("吾名:Live", 19));
            }
        });

        mAlone.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testViewModel.getAlone().postValue("小小笑话可笑可笑");
            }
        });
    }
}
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-24 18:35:55  更:2021-12-24 18:37:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:49:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码