Android开发 MutableLiveData 简单使用说明

背景

项目中有用到生命周期感知型组件 MutableLiveData,它是 LiveData 的子类,这里主要介绍 MutableLiveData 在项目中的简单使用。


一些优点

  • 不用担心发生内存泄漏
  • 可以做到在组件处于激活状态的时候才会回调相应的方法,从而刷新相应的 UI
  • 不需要手动取处理数据的储存和恢复。它已经帮我们封装好了

注意:当 Actiivty 不是处于激活状态的时候,如果你想 livedata setValue 之后立即回调 obsever 的
onChange 方法,而不是等到 Activity 处于激活状态的时候才回调 obsever 的 onChange 方法,你可以使用
observeForever 方法,但是你必须在 onDestroy 的时候 removeObserver


生命周期感知型组件的用例

生命周期感知型组件可使您在各种情况下更轻松地管理生命周期。下面列举几个例子:

  • 在粗粒度和细粒度位置更新之间切换。使用生命周期感知型组件可在位置应用可见时启用细粒度位置更新,并在应用位于后台时切换到粗粒度更新。借助生命周期感知型组件 LiveData,应用可以在用户使用位置发生变化时自动更新界面。
  • 停止和开始视频缓冲。使用生命周期感知型组件可尽快开始视频缓冲,但会推迟播放,直到应用完全启动。此外,应用销毁后,您还可以使用生命周期感知型组件终止缓冲。
  • 开始和停止网络连接。借助生命周期感知型组件,可在应用位于前台时启用网络数据的实时更新(流式传输),并在应用进入后台时自动暂停。
  • 暂停和恢复动画可绘制资源。借助生命周期感知型组件,可在应用位于后台时暂停动画可绘制资源,并在应用位于前台后恢复可绘制资源。

添加依赖

现在 Lifecycle 稳定的版本是 2.2.0,可以通过开发者库说明中查找,如下图示:

Android开发 MutableLiveData 简单使用说明_第1张图片

app模块下的build.gradle文件中添加如下:

Android开发 MutableLiveData 简单使用说明_第2张图片

代码块为:

dependencies {
    def lifecycle_version = "2.2.0"
    implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
    
    ...
}

可以通过 androidx.lifecycle 2.2.0 来了解 2.2.0 版本的一些变化调整。


MutableLiveData 源码

如下:

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.lifecycle;

/**
 * {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method.
 *
 * @param  The type of data hold by this instance
 */
@SuppressWarnings("WeakerAccess")
public class MutableLiveData<T> extends LiveData<T> {

    /**
     * Creates a MutableLiveData initialized with the given {@code value}.
     *
     * @param value initial value
     */
    public MutableLiveData(T value) {
        super(value);
    }

    /**
     * Creates a MutableLiveData with no value assigned to it.
     */
    public MutableLiveData() {
        super();
    }

    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

可以看到 MutableLiveDataLiveData 的子类,并且 MutableLiveData 中的数据类型为 T,很方便我们在 ViewModel 中实例化 MutableLiveData ,并在泛型中表明数据的类型即可(比如可以是一个实体类),所以这里使用 MutableLiveData 来作一个简单说明。


创建一个 ViewModel 的子类

package com.imxiaoqi.mutablelivedatademo.view_model;

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

/**
 * 创建 DataViewModel 继承 ViewModel
 */
public class DataViewModel extends ViewModel {

    // 声明一个 MutableLiveData 类型的变量,数据类型为 String
    private MutableLiveData<String> myStr = new MutableLiveData<>();

    // 生成 get 和 set 方法
    public MutableLiveData<String> getMyStr() {
        return myStr;
    }

    public void setMyStr(MutableLiveData<String> myStr) {
        this.myStr = myStr;
    }
}


ViewModelActivity 绑定

DataViewModel dataViewModel = null;

if (dataViewModel == null){
            // 创建 DataViewModel 对象,让 DataViewModel 和 Activity 进行绑定
            dataViewModel = new ViewModelProvider(this).get(DataViewModel.class);
        }

获取被观察对象并添加到观察者列表中

// 获取被观察对象 - 这里为 MutableLiveData 对象
        mutableLiveData = dataViewModel.getMyStr();
        // 将 mutableLiveData 添加到观察者列表中
        mutableLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                // 当被观察者对象 mutableLiveData 值发生改变时,会调用该方法,从而刷新相应 UI
                Toast.makeText(MainActivity.this, "onChange = " + s, Toast.LENGTH_SHORT)
                        .show();
            }
        });

这里被观察这对象为 MutableLiveData 对象。


改变 MutableLiveData 对象(数据源)的值

可以使用 setValue()postValue() 方法,这里使用 setValue() ,如下:

// 按钮单击事件
        findViewById(R.id.btn_change).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 改变被观察对象 - mutableLiveData 的值,使用 setValue方法改变数据源
                mutableLiveData.setValue("改变,现在时间为:" +
                        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                                .format(new Date(System.currentTimeMillis())));

            }
        });

两者区别:

  • setValue 方法必须在主线程调用
  • postValue 方法将任务发送到主线程以设置给定的值

大家看方法对应源码说明可知,不细说了:

/**
     * Posts a task to a main thread to set the given value. So if you have a following code
     * executed in the main thread:
     * 
     * liveData.postValue("a");
     * liveData.setValue("b");
     * 
* The value "b" would be set at first and later the main thread would override it with * the value "a". *

* If you called this method multiple times before a main thread executed a posted task, only * the last value would be dispatched. * * @param value The new value */ protected void postValue(T value) { boolean postTask; synchronized (mDataLock) { postTask = mPendingData == NOT_SET; mPendingData = value; } if (!postTask) { return; } ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable); } /** * Sets the value. If there are active observers, the value will be dispatched to them. *

* This method must be called from the main thread. If you need set a value from a background * thread, you can use {@link #postValue(Object)} * * @param value The new value */ @MainThread protected void setValue(T value) { assertMainThread("setValue"); mVersion++; mData = value; dispatchingValue(null); }


完整代码

package com.imxiaoqi.mutablelivedatademo;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;

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

import com.imxiaoqi.mutablelivedatademo.view_model.DataViewModel;

import java.text.SimpleDateFormat;
import java.util.Date;

public class MainActivity extends AppCompatActivity {

    DataViewModel dataViewModel = null;
    MutableLiveData<String> mutableLiveData = null;

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

        observeData();

        // 按钮单击事件
        findViewById(R.id.btn_change).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 改变被观察对象 - mutableLiveData 的值,使用 setValue方法改变数据源
                mutableLiveData.setValue("改变,现在时间为:" +
                        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                                .format(new Date(System.currentTimeMillis())));

            }
        });
    }

    /**
     * 观察数据
     */
    private void observeData() {

        if (dataViewModel == null){
            // 创建 DataViewModel 对象,让 DataViewModel 和 Activity 进行绑定
            dataViewModel = new ViewModelProvider(this).get(DataViewModel.class);
        }

        // 获取被观察对象 - 这里为 MutableLiveData 对象
        mutableLiveData = dataViewModel.getMyStr();
        // 将 mutableLiveData 添加到观察者列表中
        mutableLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                // 当被观察者对象 mutableLiveData 值发生改变时,会调用该方法,从而刷新相应 UI
                Toast.makeText(MainActivity.this, "onChange = " + s, Toast.LENGTH_SHORT)
                        .show();
            }
        });

    }
}

演示

Android开发 MutableLiveData 简单使用说明_第3张图片


参考

  • Android开发 LiveData与MutableLiveData详解
  • Android LiveData 使用详解

推荐同学们也阅读一下,加深理解。


技术永不眠,我们下期见!

你可能感兴趣的:(技术分享类,安卓开发技术学习,android,LiveData,MutableLiveData,生命周期组件,观察模式)