IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Fragment + viewModel 导致onChanged方法多次调用 -> 正文阅读

[移动开发]Fragment + viewModel 导致onChanged方法多次调用

问题描述:在使用Fragment + ViewModel时如果进行Fragment切换时,即Fragment的生命周期由onDestroyView再到onCreateView时。如果ViewModel数据发生改变,则会导致onChanged方法多次执行。

伪码如下:

public class MyFragment extends Fragment {
    private MyViewModel viewModel;
       public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
	    ···
	    	//获取viewModel对象,该viewModel并非是创建,它获取的是该Fragment挂载的Activity那个ViewModel
        	viewModel=
                new ViewModelProvider(getActivity()).get(MyViewModel .class);
        ···
        init();
       }
      init(){
      	    viewModel.getData().observe(getViewLifecycleOwner(), new Observer<String>() {
            	@Override
           		public void onChanged(String s) {
            	···
            	}
            }
      }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
}

上述伪码会导致onChange方法多次执行。通过debugger不难发现,在进行页面切换并回切的过程中,首先执行onDestroyView方法然后再次执行onCreateView方法。根绝Fragment的生命周期:
在这里插入图片描述
在整个过程中该Fragment并为被销毁,通俗来说,onCreateView方法一直是就一个对象再执行,那么observe方法也在切换的过程中重复执行,该方法的注解如下:

     * Adds the given observer to the observers list within the lifespan of the given
     * owner. The events are dispatched on the main thread. If LiveData already has data
     * set, it will be delivered to the observer.
     * 
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }

也就是说将一个观察者添加到观察者列表中,再这个过程中owner进过了进一步处理,观察者列表为Map形式,由于 owner.getLifecycle().addObserver(wrapper);方法添加的是被封装的LifecycleBoundObserver 对象,而且该类并为重写equip方法,因此每次添加的观察者的hash值都不相同,也就是说观察者列表允许添加重复的观察者对象。
回到刚才的问题。重复执行observe方法,就会重复将该观察者添加到观察者列表中,因此onchange方法也会重复执行。

解决方法

其实解决该问题只需要在调用onDestroyView方法时将已经注册的观察者从观察者列表中移出便可。具体方法如下:

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
        // 将这个观察者从观察者列表移出
        viewModel.getData().removeObservers(getActivity());
    }

思考:viewModel的观察者列表是否会导致内存泄漏?移出观察者是不是就可以避免ViewModel导致的内存泄漏问题。

解决方法2

在fragment中注册贯彻者时不要使用getActivity()作为观察者对象(本身也不建议这么使用,如果注册activity为观察者对象,Frament移除时观察者依旧能观察)使用以下代码:

.observe(getViewLifecycleOwner(),e->{});

方法2思考:使用getActivity()作为观察者,页面切换回来后,如果onChanged方法中调用了databing,那么再次调用onChanged方法时会导致databing为null异常。该问题可能是由于观察者内部不存在databing对象?
如有问题欢迎斧正

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 22:21:45  更:2022-03-11 22:22:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 18:29:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码