栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

组件化之路 - LiveData + ViewModel一知半解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

组件化之路 - LiveData + ViewModel一知半解

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

Android Architecture Components 架构组件

  • 组件化之路 - LiveData一知半解
  • 组件化之路 - LiveData + ViewModel一知半解

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

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

        • 基本认知
        • 基础实现
          • 官网示例
          • 自我演练
          • 单串演练
        • 完整Demo

基本认知

其实在学习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> users;
    public LiveData> getUsers() {
        if (users == null) {
            users = new MutableLiveData>();
            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 selected = new MutableLiveData();

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

    public LiveData 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;


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;


public class TestViewModel extends ViewModel {
    private MutableLiveData liveData;
    
    public LiveData getTestViewModel() {
        if (liveData == null) {
            liveData = new MutableLiveData();
        }
        return liveData;
    }
    
    
     public void setTestViewModel(TestModel testModel) {
        liveData.postValue(testModel);
    }
    
    
    @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() {
            @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;


public class TestViewModel extends ViewModel {
    private MutableLiveData mutableLiveData;

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

    
    @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() {
            @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;


public class TestViewModel extends ViewModel {
    private MutableLiveData stringMutableLiveData;

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

    
    @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() {
            @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;


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;


public class TestViewModel extends ViewModel {
    private MutableLiveData liveData;
    private MutableLiveData mutableLiveData;
    private MutableLiveData stringMutableLiveData;

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

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

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

    MutableLiveData getAlone() {
        if (stringMutableLiveData == null) {
            stringMutableLiveData = new MutableLiveData<>();
        }
        return stringMutableLiveData;
    }
    
    
    @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() {
            @Override
            public void onChanged(TestModel testModel) {
                mTest.setText("姓名:" + testModel.getName() + " - 年龄:" + testModel.age);
            }
        });

        testViewModel.getAlone().observe(this, new Observer() {
            @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("小小笑话可笑可笑");
            }
        });
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/677540.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号