Jetpack系列全解析

一、什么是Jetpack?

Jetpack并不是一个框架或者组件,它是一套库、工具和指南的集合,可帮助开发者更轻松地编写优质应用。这些组件可帮助开发者遵循最佳做法、摆脱编写样板代码的工作并简化复杂任务,以便将精力集中放在所需的代码上。
Android Jetpack中的很多组件并不都是新开发的,而是很早就有了,比如在Goole I/O 2017大会时推出了 Android Architecture Component(AAC),它包括了LifeCycle、LiveData、ViewModel、Room。在Goole I/O 2018大会上,
用AndroidX替代了Android Support Library,并在Android Architecture Component的基础上发布了Android Jetpack,AndroidX也是属于Android Jetpack。

Jetpack主要特性有以下三点:

1.加速开发
组件可单独使用,也可以协同工作,当使用kotlin语言特性时,可以提高效率。
2.消除样板代码
Android Jetpack可管理繁琐的Activity(如后台任务、导航和生命周期管理)。
3.构建高质量的强大应用
Android Jetpack组件围绕现代化设计实践构建而成,具有向后兼容性,可以减少崩溃和内存泄漏。

二、Android Jetpack架构组件 Lifecycle

2.1 什么是Lifecycle

Lifecycle用于帮助开发者管理Activity和Fragment 的生命周期

2.2 Lifecycle基本用法
先不谈Activity和Fragment中如何使用,先举一个Lifecycle的简单例子。

public class MyObserver implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void connectListener() {
        ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void disconnectListener() {
        ...
    }
}
myLifecycleOwner.getLifecycle().addObserver(new MyObserver());//1

复制代码新建一个MyObserver类,它实现了LifecycleObserver接口,说明MyObserver成为了一个Lifecycle的观察者。
然后在注释1处将MyObserver添加到LifecycleOwner中。LifecycleOwner是一个接口,其内部只有一个方法getLifecycle(),getLifecycle方法用于获取Lifecycle,这样就可以将MyObserver添加到Lifecycle中,当Lifecycle的生命周期发生变化时,MyObserver就会观察到,或者说是感知到。
如果使用是Java8 ,那么可以使用DefaultLifecycleObserver来替代LifecycleObserver:

class MyObserver implements DefaultLifecycleObserver {
     @Override
     public void onCreate(LifecycleOwner owner) {
         ...
     }
 }

复制代码除此之外,不要忘了在build.gradle添加 "androidx.lifecycle:common-java8:<version>"

2.3.Lifecycle应用举例

应用举例准备两个示例,在Activity中使用

package com.example.lifecycledemo1;

import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleObserver;
import android.arch.lifecycle.OnLifecycleEvent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getLifecycle().addObserver(new MyObserver());//1
    }

    public class MyObserver implements LifecycleObserver{

        @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
        void onResume(){
            Log.d(TAG, "Lifecycle call onResume");
        }
        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        void onPause(){
            Log.d(TAG, "Lifecycle call onPause");
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause");

    }
}

复制代码先实现MyObserver,对ON_CREATE和ON_RESUME事件进行监听。因为在Android Support Library 26.1.0 及其之后的版本,Activity和Fragment已经默认实现了LifecycleOwner接口,所以在注释1处可以直接使用getLifecycle方法获取Lifecycle对象,这样MyObserver就可以观察MainActivity的生命周期变化了,LifecycleOwner可以理解为被观察者,MainActivity默认实现了LifecycleOwner接口,也就是说MainActivity是被观察者。
运行程序,打印的log如下所示。

D/MainActivity: onResume
D/MainActivity: Lifecycle call onResume
D/MainActivity: Lifecycle call onPause
D/MainActivity: onPause

只要在MainActivity的onCreate方法中添加MyObserver,那么MyObserver就可以观察到MainActivity的各个生命周期的变化。

三、Android Jetpack架构组件 LiveData

3.1 什么是LiveData

LiveData是一个感知数据变化的持有者,一般是感知Viewmodel的数据!

LiveData如同它的名字一样,是一个可观察的数据持有者,和常规的observable不同,LiveData是具有生命周期感知的,这意味着它能够在Activity、Fragment、Service中正确的处理生命周期。
LiveData的数据源一般是ViewModel,也可以是其它可以更新LiveData的组件。当数据更新后,LiveData 就会通知它的所有观察者,比如Activiy。与RxJava的方法不同的是,LiveData并不是通知所有观察者,它 只会通知处于Active状态的观察者,如果一个观察者处于Paused或Destroyed状态,它将不会收到通知。
这对于Activiy和Service特别有用,因为它们可以安全地观察LiveData对象而不用担心内存泄漏的问题。开发者也不需要在onPause或onDestroy方法中解除对LiveData的订阅。还有一点需要注意的是一旦观察者重新恢复Resumed状态,它将会重新收到LiveData的最新数据。

image.png

3.2 LiveData的基本用法
LiveData是一个抽象类,它的最简单的实现类为MutableLiveData,这里举个最简单的例子。

public class MainActivity extends AppCompatActivity {
   private static final String TAG="MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MutableLiveData<String> mutableLiveData  = new MutableLiveData<>();
        //观察者,观察到数据变化显示出来
        mutableLiveData.observe(this, new Observer<String>() {//1
            @Override
            public void onChanged(@Nullable final String s) {
                Log.d(TAG, "onChanged:"+s);
            }
        });
        //被观察者数据,异步线程运行
        mutableLiveData.postValue("Android进阶三部曲");//2
    }
}

注释1处的observe方法有两个参数分别是LifecycleOwner和 Observer<T> ,第一个参数就是MainActivity本身,第二个参数新建了一个Observer<String>,在onChanged方法中得到回调。注释处的postValue方法会在主线程中更新数据,这样就会得到打印的结果。

D/MainActivity: onChanged:Android进阶三部曲

在大多数情况下,LiveData的observe方法会放在onCreate方法中,如果放在onResume方法中,会出现多次调用的问题。除了MutableLiveData的postValue方法,还可以使用setValue方法,它们之前的区别是,setValue方法必须在主线程使用,如果是在工作线程中更新LiveData,则可以使用postValue方法。

3.3 LiveData源码分析


         model.getLiveData().observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String newName) {
                //响应接受的消息
                tvReceiveData.setText(newName);
            }
        });

           1.这个代码必须放到主线程,不然崩溃assertMainThread("observe");

           2.Activity生命周期销毁了的话直接退出不执行,所以不会引发内存泄漏
           if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                  return;
             }

           3.LifecycleBoundObserver装饰器,封装LifecycleOwner,Observer这两个对象

           4.owner.getLifecycle().addObserver(wrapper);将观察者与LifecycleOwner进行绑定

           5.Activity销毁就取消订阅,因此不会内存泄漏


============================================================================

         model.getLiveData().setValue("我是点击按钮发送的消息");

         1.for循环遍历所有的观察者
         2.调用观察者的observer.mObserver.onChanged((T) mData);因此在每个观察者的onChanged方法可以监听到数据变化。

总结:

1.LiveData 是如何跟 LifecycleOwner 进行绑定,做到感知生命周期的?
答:LifeData 在 observe 方法中用 LifecycleBoundObserver 包装了 observer ,并且通过它绑定了owner。

2.LiveData 会自动在 DESTROY 的状态下取消订阅,是怎么处理的?
答:LifecycleBoundObserver 在 onStateChanged() 方法里处理了生命周期改变的事件,当接收到 DESTROYED 的事件会自动解除跟 owner 的绑定。

生命周期变化后数据处理流程是怎么样的?

LiveData 的实现基于观察者模式;
LiveData 跟 LifecycleOwner 绑定,能感知生命周期变化,并且只会在 LifecycleOwner 处于 Active 状态(STARTED/RESUMED)下通知数据改变;如果数据改变发生在非 active 状态,数据会变化,但是不发送通知,等 owner 回到 active 的状态下,再发送通知;
LiveData 会自动在 DESTROYED 的状态下移除 Observer ,取消订阅,所以不用担心内存泄露;
在 LifecycleOwner 处于 DESTROYED 的状态下,不能订阅;
postValue 方法其实最后调用了 setValue 只不过把操作放到主线程,适合在异步线程里调用,setValue 必须在主线程里调用;
如果同时多次调用 postValue 或 setValue 修改数据,只会修改成最新的那个数据,也即只会收到一次通知(set post混合调用则不一定);
如果 LiveData 有数据,并且 owner 在 active 状态下,那么在订阅的时候,会立马收到一次通知;
一个 Observer 实例,只能绑定一个 LifecycleOwner,而一个 owner 可以绑定多个 Observer 实例;
LiveData 利用版本管理、绑定 Lifecycle 确保了只会发送最新的数据给 active 状态下的 Observer;

LiveData 基于观察者模式,并且可以感知生命周期,这使得我们使用 LiveData 既可以享受观察者模式带来的隔离数据与 UI 等强大的解耦能力,还可以享受感知生命周期带来的巨大便利。并且还无需担心内存泄露这个令人头疼的问题。

四、Android Jetpack架构组件 ViewModel

4.1.什么是ViewModel

ViewModel,感知生命周期的形式来存储和管理视图相关的数据。针对数据。

在说ViewModel前,我们需要解一下MVVM和DataBinding.MVVM最早于2005年被微软的架构师John Gossman提出,在2015年Google I/O大会上发布了MVVM的支持库DataBinding,DataBinding遭到了一些开发者的诟病,主要是绑定数据时如果出现问题会很难排查,这样就没有一个合适的ViewModel规范来帮助开发者来实现MVVM。
在2017年的Google I/O大会上,谷歌推出了ViewModel组件,来规范化ViewModel层。
ViewModel顾名思义,是以感知生命周期的形式来存储和管理视图相关的数据。ViewModel主要有以下的特点:
1.当Activity被销毁时,我们可以使用onSaveInstanceState()方法恢复其数据,这种方法仅适用于恢复少量的支持序列化、反序列化的数据,不适用于大量数据,如用户列表或位图。而ViewModel不仅支持大量数据,还不需要序列化、反序列化操作。
2.Activity/Fragment(视图控制器)主要用于显示视图数据,如果它们也负责数据库或者网络加载数据等操作,那么一旦逻辑过多,会导致视图控制器臃肿,ViewModel可以更容易,更有效的将视图数据相关逻辑和视图控制器分离开来。
3.视图控制器经常需要一些时间才可能返回的异步调用,视图控制器需要管理这些调用,在合适的时候清理它们,以确保它们的生命周期不会大于自身,避免内存泄漏。而ViewModel恰恰可以避免内存泄漏的发生。

4.2.ViewModel基本使用
自定义ViewModel继承ViewMode,实现自定义ViewModel。

import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;

public class MyViewModel extends ViewModel {
    private MutableLiveData<String> name;
    public LiveData<String> getName() {
        if (name == null) {
            name = new MutableLiveData<String>();
            addName();
        }
        return name;
    }
    private void addName() {
        name.setValue("Android进阶解密");
    }
}

getName方法中创建一个MutableLiveData,并通过MutableLiveData的setValue方法来更新数据。
使用ViewModel然后就可以在Activity中使用MyViewModel了,如下所示。

import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getName().observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable String s) {
                   Log.d(TAG, "畅销书:"+s);
            }
        });
    }
}

通过ViewModelProviders就可以获得MyViewModel的实例,然后配合LiveData就可以观察Name的变化。打印结果为:

D/MainActivity: 书名为Android进阶解密

4.3.ViewModel的生命周期

在旋转设备屏幕时,Activity会被销毁重新创建,而ViewModel却不会这样,它的生命周期如下所示。


image.png

可以看到,Activity的生命周期不断变化,经历了被销毁重新创建,而ViewModel的生命周期没有发生变化。

4.4 ViewModel源码解析

        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);

          1.ViewModel是怎么创建的?   
               get方法里面反射实例化ViewModel
          2.ViewModel是怎么存储的?  
                 ViewModelStore mViewModelStore;
                  ViewModelStore 结构:HashMap<String, ViewModel> 
                  mViewModelStore.put(key, viewModel);
          3.ViewModel为什么可以实现屏幕旋转不丢失数据?   屏幕状态发生改变会拿到上一次屏幕旋转的值

        NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
        ViewModelStore mViewModelStore = nc.viewModelStore;
        每次拿到上次屏幕旋转的ViewModelStore ,从而拿到ViewModel 

参考资料:
Android Jetpack架构组件(一)带你了解Android Jetpack
https://juejin.cn/post/6844903976815558663

Android Jetpack架构组件(二)一文带你了解Lifecycle(使用篇)
https://juejin.cn/post/6844903977788801032

Android Jetpack架构组件(三)一文带你了解Lifecycle(原理篇)
https://juejin.cn/post/6844903977788817416

Android Jetpack架构组件(四)一文带你了解LiveData(使用篇)
https://juejin.cn/post/6844903982691794957

Android Jetpack架构组件(五)一文带你了解LiveData(原理篇)
https://juejin.cn/post/6844903982691794952

Android Jetpack架构组件(六)一文带你了解ViewModel的使用和原理
https://juejin.cn/post/6844903983471935495

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容