资讯专栏INFORMATION COLUMN

android-lifecycle笔记

kk_miles / 1332人阅读

摘要:的职责是为或者管理数据如何获取一个继承或者如果你需要在中使用上下文对象可以继承如果继承构造函数必须有一个类型的参数并且只能是而不是其子类在或者中获取实例对象的唯一性如果一个未被销毁那么多次获取得到的是同一个实例对象从源码中去分析这个逻辑先看

ViewModel

ViewModel的职责是为Activity或者Fragment管理数据.

如何获取一个ViewModel?

继承ViewModel或者AndroidViewModel

 class MyViewModel : ViewModel(){
     
 }
 
 //如果你需要在ViewModel中使用上下文对象,可以继承AndroidViewModel
class MyViewModel2(var application : Application) : AndroidViewModel(){
    
}
 
如果继承AndroidViewModel,构造函数必须有一个Application类型的参数,并且只能是Application,而不是其子类.

Activity或者Fragment中获取MyViewModel实例对象

 val myViewModel = ViewModelProviders.of(activity/fragment).get(MyViewModel::class.java)
ViewModel的唯一性

如果一个Activity/Fragment未被销毁,那么多次获取ViewModel,得到的是同一个实例对象.
从源码中去分析这个逻辑.
先看ViewModelPoviders.of()这个方法,返回一个ViewModelProvider对象

    public static ViewModelProvider of(@NonNull Fragment fragment) {
        return of(fragment, null);
    }
    
    public static ViewModelProvider of(@NonNull FragmentActivity activity) {
        return of(activity, null);
    }

这里只看Activity的

     public static ViewModelProvider of(@NonNull FragmentActivity activity,
            @Nullable Factory factory) {
        Application application = checkApplication(activity);
        if (factory == null) {
            factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
        }
        return new ViewModelProvider(ViewModelStores.of(activity), factory);
    }

看一下ViewModelProvider这个构造函数

  public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
        mFactory = factory;
        this.mViewModelStore = store;
    }

当获取到ViewModelProvider对象后,调用其get方法获取到MyViewModel的实例对象
看一下get方法

    
    public  T get(@NonNull Class modelClass) {
        String canonicalName = modelClass.getCanonicalName();
        if (canonicalName == null) {
            throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
        }
        return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
    }
    
    
     public  T get(@NonNull String key, @NonNull Class modelClass) {
     //从ViewModelStore中获取ViewModel对象
        ViewModel viewModel = mViewModelStore.get(key);

        if (modelClass.isInstance(viewModel)) {
            //noinspection unchecked
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }

        viewModel = mFactory.create(modelClass);
        mViewModelStore.put(key, viewModel);
        //noinspection unchecked
        return (T) viewModel;
    }

从这里可以看到是从ViewModelStore中获取ViewModel对象.在ViewModelStore中封装了一个HashMap对象.如果HashMap对象中存储了ViewModel对象,就直接复用,如果ViewModel对象未创建,就重新创建后存储在HashMap中.

要保证ViewModel是唯一的,ViewModelStore就必须是唯一的.看一下ViewModelStore是如果获取到的.
在给ViewModelProvider传参数时调用了ViewModelStores.of(activity),看一下这一步做了什么?

//ViewModelStores.java
public static ViewModelStore of(@NonNull FragmentActivity activity) {
        if (activity instanceof ViewModelStoreOwner) {
            return ((ViewModelStoreOwner) activity).getViewModelStore();
        }
        return holderFragmentFor(activity).getViewModelStore();
    }

查看安卓源码发现,support包下的Fragment和FragmentActivity都继承了ViewModelStoreOwner,自然要实现其方法.

    //FragmentActivity
     public ViewModelStore getViewModelStore() {
        if (this.getApplication() == null) {
            throw new IllegalStateException("Your activity is not yet attached to the Application instance. You can"t request ViewModel before onCreate call.");
        } else {
            if (this.mViewModelStore == null) {
                FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance();
                if (nc != null) {
                    this.mViewModelStore = nc.viewModelStore;
                }

                if (this.mViewModelStore == null) {
                    this.mViewModelStore = new ViewModelStore();
                }
            }

            return this.mViewModelStore;
        }
    }

可以看出,对于一个未销毁的Activity或者Fragment,其ViewModelStore对象是唯一的.那么其存储的ViewModel对象也是唯一的.

ViewModel的特点

由上面可知,Activity或者Fragment未被销毁,ViewModel是唯一的,那么其保存的数据也是不变的,当Activity发生了屏幕旋转等变化时,仍旧可以复用ViewModel中的数据.

不要持有View层的引用

ViewModel内部不要持有View层的引用,比如Activity或者Fragment.可以和LiveData结合使用

生命周期

由图可看出,Activity重建前后,ViewModel保持不变.
LiveData

LiveData持有数据,并可在给定的生命周期内被观测.
继承关系如下:
[LiveData] ^- [MutableLiveData] ^- [MediatorLiveData]

MutableLiveData对外暴露setValuepostValue.
MediatorLiveData观察别的LiveData.并能将active/inactive状态传递给它所观察的LiveData对象.

postValue与setValue

postValue可以从后台线程更新数据,setValue只能在主线程中更新数据.如果同时调用这两个方法,postValue设置的数据会覆盖code>setValue设置的数据.postValue是通过ArchTaskExecutor来实现在主线程中更新数据.在ArchTaskExecutor中使用主线程的Handler.

observeForever与removeObserver

如果一个观察者通过observeForever被添加,这个观察者会被认为一直处于激活状态,任何数据更新都会立即通知到它.因此需要手动调用removeObserver去移除它.

onActive与onInactive Lifecycle

v4包下的SupportActivityFragment默认都实现了LifecycleOwner(API27+),并且都默认初始化了lifeCycle实例

  //LifecycleOwner
  public interface LifecycleOwner {
    /**
     * Returns the Lifecycle of the provider.
     *
     * @return The lifecycle of the provider.
     */
    @NonNull
    Lifecycle getLifecycle();
}

//supportActivity
public class SupportActivity extends Activity implements LifecycleOwner, Component {
   
    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    
      public Lifecycle getLifecycle() {
        return this.mLifecycleRegistry;
    }
}



public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
        ViewModelStoreOwner {
         LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
}

public class LifecycleRegistry extends Lifecycle {
 //.........
}
LifecycleObserver

如果你使用的是java8,可以通过添加以下依赖来使用DefaultLifecycleObserver

android.arch.lifecycle:common-java8:

然后实现DefaultLifecycleObserver

 class TestObserver implements DefaultLifecycleObserver {
     @Override
     public void onCreate(LifecycleOwner owner) {
          // your code
      }
  }

如果使用的是java7,通过注解来监听生命周期事件.并且可以给对用的生命周期方法添加一个LifecycleOwner参数.如果方法被Lifecycle.Event.ON_ANY注解,那么该方法可以额外添加一个Lifecycle.Event.ON_ANY参数.

 class TestObserver implements LifecycleObserver {
     @OnLifecycleEvent(ON_CREATE)
    void onCreated(LifecycleOwner source) {}
     @OnLifecycleEvent(ON_ANY)
    void onAny(LifecycleOwner source, Event event) {}
  }
google官方MVVM架构图

由图可以看出,不管数据从哪里来,最终要汇聚到数据仓库,LiveData观察的是数据仓库的变化.并且ViewModel中可以定义多个LiveData.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/14845.html

相关文章

  • Android-Lifecycle超能解析-生命周期的那些事儿

    摘要:将的生命周期函数对应成,生命周期改变,会造成改变,而变化将触发事件,从而被接收。与一样,都是通过注册来监听的生命周期回调,来给每个添加的。 版权声明:本文已授权微信公众号:Android必修课,转载请申明出处众所周知,Android凡是需要展示给用户看的,都包含着生命周期这个概念,例如Activity、Fragment、View等都与生命周期息息相关,在生命周期函数里,它们各自完成创...

    Keven 评论0 收藏0
  • Android-Lifecycle超能解析-生命周期的那些事儿

    摘要:将的生命周期函数对应成,生命周期改变,会造成改变,而变化将触发事件,从而被接收。与一样,都是通过注册来监听的生命周期回调,来给每个添加的。 版权声明:本文已授权微信公众号:Android必修课,转载请申明出处众所周知,Android凡是需要展示给用户看的,都包含着生命周期这个概念,例如Activity、Fragment、View等都与生命周期息息相关,在生命周期函数里,它们各自完成创...

    ralap 评论0 收藏0
  • fir.im Weekly - 聊聊让人向往的远程开发工作

    摘要:本质上就是你调用苹果提供给你的来完成设计师的设计。如果能做到烂熟于胸,相信会有很大的提升。除此外,推荐下他整理的开发者项目最佳实践,资料很多很强大。感谢简书作者翻译,造福广大开发者。 6月30 日,苹果开发者后台贴出一封关于广电总局的醒目通知,申报一个游戏 APP 上架AppStore,你需要文网文+ICP证+软著+版号,审批难度将越来越大,不禁让人感慨中国独立开发者的成长 道阻且长...

    孙淑建 评论0 收藏0
  • fir.im Weekly - 聊聊让人向往的远程开发工作

    摘要:本质上就是你调用苹果提供给你的来完成设计师的设计。如果能做到烂熟于胸,相信会有很大的提升。除此外,推荐下他整理的开发者项目最佳实践,资料很多很强大。感谢简书作者翻译,造福广大开发者。 6月30 日,苹果开发者后台贴出一封关于广电总局的醒目通知,申报一个游戏 APP 上架AppStore,你需要文网文+ICP证+软著+版号,审批难度将越来越大,不禁让人感慨中国独立开发者的成长 道阻且长...

    dreambei 评论0 收藏0
  • 大部分程序员都记不住的注解,Idea 云笔记却能轻松记住

    摘要:只因技术种类繁杂众多层出不穷,程序员只有靠不断的学习才能不落后于技术,被工作淘汰。特此推荐给大家。 99%的程序员每天都是先学习,后工作,不然完成不了工作。只因技术种类繁杂众多、层出不穷,程序员只有靠不断的学习才能不落后于技术,被工作淘汰。我就是这其中一员,深得体会其中的「疼并快乐」,在...

    ARGUS 评论0 收藏0

发表评论

0条评论

kk_miles

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<