Android 多个Activity(Fragment)之间共享一个ViewModel对象,并扩展作用域注解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 多个Activity(Fragment)之间共享一个ViewModel对象,并扩展作用域注解相关的知识,希望对你有一定的参考价值。

参考技术A 查看源码后发现ViewModel是否会复用和两个因素有关,一个是ViewModelStore(用于保存ViewModel实例),另一个是get方法传入的key,如下:

由此我们可以定义一个注解用于标记view model的作用域

然后通过自定义ViewModelStore来解决view model复用问题

使用方式:
界面Activity1

界面Activity2

界面Fragment

查看结果

混淆配置(如果开启混淆,则需加入下列配置,否则会导致注入失败)

Tip:
该实现方式由于基于反射实现,所以运行开销较大,也不支持创建带参数View Model所以已被弃用,请参考二期优化后的实现方式:
https://www.jianshu.com/p/79d70b2712ee

项目地址: https://github.com/LucasDevelop/CustomView . 中的View model 案例

Fragment与ViewPager

众所周知,为了实现滑动界面,经常让FragmentViewPager一起结合使用,每一个ViewPager的页面就是一个Fragment,我们可以在fragment中实现丰富的功能。
它的基本用法可以是下面这样

1、创建一个或者多个你需要的Fragment类,其实就是类似activity一样,也有OnCreate()等回调函数。
fragmentsList = new ArrayList<Fragment>(); Fragment a = new aFragment(); Fragment b = new bFragment(); Fragment c= new cFragment(); fragmentsList.add(a); fragmentsList.add(b); fragmentsList.add(c); mPager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager(), fragmentsList)); mPager.setCurrentItem(0); mPager.setOnPageChangeListener(new MyOnPageChangeListener()); mPager.setOffscreenPageLimit(3); // 同时加载3个fragment

 

它的适配器:

import java.util.ArrayList;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {//这里继承的是FragmentPagerAdapter
    private ArrayList<Fragment> fragmentsList;

    public MyFragmentPagerAdapter(FragmentManager fm) {
        super(fm);
    }
    public MyFragmentPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragments) {
        super(fm);
        this.fragmentsList = fragments;
    }

    @Override
    public int getCount() {
        return fragmentsList.size();
    }

    @Override
    public Fragment getItem(int arg0) {
        return fragmentsList.get(arg0);
    }

    @Override
    public int getItemPosition(Object object) {
        return super.getItemPosition(object);
    }

}

上面的适配器继承的是FragmentPagerAdapter,除此之外还可以继承FragmentStatePagerAdapter,但是两者是有区别的。
1.FragmentPagerAdapter继承自PagerAdapter ,主要用来展示多个Fragment页面,并且每一个Fragment都会被保存在fragment manager中,最适用于那种少量且相对静态的页面,用户访问过的fragment都会被保存在内存中,尽管他的视图层级可能会在不可见时被销毁。
    

2.FragmentStatePagerAdapter继承自PagerAdapter,主要使用Fragment来管理每个页面。这个类同样用来保存和恢复fragment页面的状态,更多用于大量页面,例如视图列表。当某个页面对用户不再可见时,他们的整个fragment就会被销毁,仅保留fragment状态。相比于FragmentPagerAdapter,这样做的好处是在访问各个页面时能节约大量的内存开销,但代价是在页面切换时会增加非常多的开销。

 

他们之间最大的不同在于用户访问过的页面不可见之后是否会保留在内处于存中。

 

我们都知道:ViewPager为了保证滑动的流畅性,viewpager在加载当前页的时候已经将pager页左右页的内容加载进内存里了(预加载机制)。当滑动到第n页的时候,adapter会为相邻两页创建Fragment实例。FragmentPagerAdapterFragmentStatePagerAdapter在这一点是一样的。

但是对于上上页:

FragmentPagerAdapter的做法:上上页实例保留,但是摧毁它的视图。

FragmentStatePagerAdapter的做法:果断摧毁上上页的实例(我不留情)。

 

注意:adaptergetItem()方法是当fragment不存在的时候才被调用,返回的是Fragment的实例。因此对于FragmentPagerAdapter,当每页的Fragment被创建后,这个函数就不会被调到了。而对于FragmentStatePagerAdapter则不然。

 

 

卸载不再需要的fragment

1.FragmentStatePagerAdapter:选择用remove(Fragment)方法将fragmentactivityFragmentManager中彻底移除,在销毁 fragment时,它会将 其 onSaveInstanceState(Bundle) 方法中的Bundle信息保存下来。用户切换回原来的页面后,保存的实例状  态可用于恢复生成新的fragment.

 

2. FragmentPagerAdapter:选择调用事务的detach(Fragment) 方法,FragmentPagerAdapter只是销毁了fragment的视 图,但仍将 fragment实例保留在FragmentManager中。因此, FragmentPagerAdapter创建的fragment永远不会被销毁。

 

警戒区:
1.ViewPager.getChildCount() 返回的是当前ViewPager所管理的没有被销毁视图的Fragment,并不是所有的Fragment。想要获取所有的Fragment数量,应该调用ViewPager.getAdapter().getCount().

2.主Activity要继承FragmentActivity,只有FragmentActivity内部才能内嵌Fragment普通Activity是不行的。

3.activityFragment都要用android.support.v4.app.Fragment,否则可能出现无法将Fragment的子类转换为Fragment的情况,会抛出转换异常。

 

以上是关于Android 多个Activity(Fragment)之间共享一个ViewModel对象,并扩展作用域注解的主要内容,如果未能解决你的问题,请参考以下文章

Android 兼容包不包含 Activity.getFragmentManager()

Fragment

Fragment与ViewPager

android 弹出多个Activity的问题

android开发源代码分析--多个activity调用多个jni库的方法

监听Activity生命周期方式及案例讲解