嗯,好吧,最近又整理了下JetPack下的Lifecycle、LivaData、ViewModels的相关知识,没想到越学越深,越整理越多,所以赶紧一起共勉一下吧 ~
Android Architecture Components 架构组件
在此之前,我看了很多 LiveData
的相关blog,但是80%的blog都会搭配 ViewModel
进行综合讲解,我此处主要讲解 LiveData
自身的使用与特性 ~
众所周知,Google一直有一套属于自己的 Jetpack(组件库) ,而其内部组件
又划分为多种类型,分别适用不同场景,其中Lifecycle、LivaData、ViewModel
隶属于 Android Architecture Components(架构化组件)
Android架构化组件是通过提供管理开发者UI 组件的生命周期和数据持久化方案的一系列库,来帮助开发者设计出,稳健性,可测试性和可维护的App应用。
公知:LiveData是一款可被观察的数据持有类组件
,内部采用了观察者模式,结合Lifecycle
管理组件生命周期等 ~
Look Here 重要的话重复说
:正式讲解LiveData前, 一定要记得LiveData是一款可被观察的数据持有类 - 组件
LiveData
之所以被开发者广泛使用,其中最重要原因就是其自带的一些特性和优势,具体如下
remark:LiveData内绑定了Lifecycle组件,可动态感知组件的生命周期,所以可以把LiveData看作是一款可感知生命周期的组件
数据实时更新
,LiveData
采用了观察者模式,在注册观察者后,只要被观察者(事件源)发生改变,即可及时捕获最新数据优化实时更新
,生命周期从非活跃状态切换到活跃状态时,才会实时通知LiveData
观察者防止内存泄漏、优化组件销毁的异常场景
,当组件生命周期处于DESTROYED
时,会自动解除LiveData和观察者的注册关系优化配置更改
,当手机横竖屏切换时也可以及时收到最新的数据资源共享
,单例模式扩展LiveData对象并包装成系统服务,以便在应用程序中进行共享,需要该资源的只需要观察LiveData即可。既然我们说到
LiveData使用了观察者模式
,自然其具备了一些模式特征,如观察者、被观察者、订阅行为、信息push
等要素 ~
LiveData为抽象类,且自身作为被观察者,主要实现类有MutableLiveData、MediatorLiveData
子类,其中"MediatorLiveData 继承自 MutableLiveData"
,所以严格来说LiveData只有一个常用的MutableLiveData
子类 ~
LiveData
MutableLiveData
MediatorLiveData
(注意:MediatorLiveData 继承自 MutableLiveData)
观察者部分
LiveData
添加的观察者主要有observe、observeForever
, 通过方法参数可以看出俩者的区别,observe()
需要传入LifecycleOwner(一般写入上下文即可),然后LiveData
会自动感知组件的生命周期,在激活状态才会收到消息
;而observeForever()会永久收到数据变化的回调
,同时当组件销毁时,需要用户手动removeObserve(),否则观察者会一直收到数据的变化的回调通知。
Tip:关于observe()、observeForver()的订阅操作必须在主线程,否则会报异常 ~
observe() - 活跃状态(STARTED、RESUMED状态)期间接收消息
observeForever()
被观察者,信息推送部分
LiveData更新(改变)数据
时,都有特定的方法(在MutableLiveData类内
都可以看到),主要有postValue()、setValue()
俩种方式,区别主要体现在setValue()仅支持主线程调用
,而postValue()在子主线程中均可被调用
(内部使用了handler自主线程通信,最后依旧通过serValue()设值),所以一般我们都使用postValue()
脑补:有时候我在想用EventBus不也ok吗?后来一想使用EventBus为了防止内存泄漏,我要及时注册、注销;同时针对不同组件的生命周期方面,其实又有点浪费性能;所以就算了 ~
postValue()
setValue()
关于LiveData使用方式主要有俩种,其一使用LiveData对象(子类),其二为继承LiveData(自定义)
综合上述,这里我单独使用 LiveData 写了一个入门Demo
build引入
// alternatively, just LiveData
implementation "android.arch.lifecycle:livedata:1.1.0"
实现步骤
创建被观察者
Livedata的实体类observe绑定观察者
,动态监听数据更新postValue() 动态更新数据
package com.example.livedata;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView mName = findViewById(R.id.tv_name);
//创建被观察者(如果已明确类型,可在泛型内进行申明)
MutableLiveData<Object> liveData= new MutableLiveData<>();
//绑定观察者
liveData.observe(this, new Observer<Object>() {
@Override
public void onChanged(Object data) {
mName.setText(data+"");
}
});
//更新数据
mName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
liveData.postValue("吾名:LiveData");
}
});
}
}
自定义LiveData(尚不完整~)
关于 observe、observeForever、setValue、postValue
方法已经详细讲解过了,这里主要说一下onActive、onInactive
方法 ~
Called when the number of active observers change to 1 from 0.
This callback can be used to know that this LiveData is being used thus should be kept up to date.
当这个方法被调用时,表示LiveData的观察者数量从0变为了1,这时就我们的位置监听来说,就应该注册我们的时间监听了。
Called when the number of active observers change from 1 to 0.
This does not mean that there are no observers left, there may still be observers but their lifecycle states aren’t STARTED or RESUMED (like an Activity in the back stack).
You can check if there are observers via hasObservers().
这个方法被调用时,表示LiveData的观察者数量变为了0,既然没有了观察者,也就没有理由再做监听,此时我们就应该将位置监听移除
Domo示例:这里我们以观察网络状态变化为例子讲解(借鉴自别处,尚未自己这部分)
首先我们自定义一个 Class NetworkLiveData,继承 LiveData,重写它的 onActive 方法和 onInactive 方法
在 onActive 方法中,我们注册监听网络变化的广播,即ConnectivityManager.CONNECTIVITY_ACTION。在 onInactive 方法的时候,我们注销广播。
public class NetworkLiveData extends LiveData<NetworkInfo> {
private final Context mContext;
static NetworkLiveData mNetworkLiveData;
private NetworkReceiver mNetworkReceiver;
private final IntentFilter mIntentFilter;
private static final String TAG = "NetworkLiveData";
public NetworkLiveData(Context context) {
mContext = context.getApplicationContext();
mNetworkReceiver = new NetworkReceiver();
mIntentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
}
public static NetworkLiveData getInstance(Context context) {
if (mNetworkLiveData == null) {
mNetworkLiveData = new NetworkLiveData(context);
}
return mNetworkLiveData;
}
@Override
protected void onActive() {
super.onActive();
Log.d(TAG, "onActive:");
mContext.registerReceiver(mNetworkReceiver, mIntentFilter);
}
@Override
protected void onInactive() {
super.onInactive();
Log.d(TAG, "onInactive: ");
mContext.unregisterReceiver(mNetworkReceiver);
}
private static class NetworkReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager manager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
getInstance(context).setValue(activeNetwork);
}
}
}
这样,当我们想监听网络变化的时候,我们只需要调用相应的 observe 方法即可,方便又快捷。
NetworkLiveData.getInstance(this).observe(this, new Observer<NetworkInfo>() {
@Override
public void onChanged(@Nullable NetworkInfo networkInfo) {
Log.d(TAG, "onChanged: networkInfo=" +networkInfo);
}
});