Android 学习之那些年我们遇到的BUG9:Lifecycle.Event.ON_RESUME 提前触发了

Posted Nicholas_hzf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 学习之那些年我们遇到的BUG9:Lifecycle.Event.ON_RESUME 提前触发了相关的知识,希望对你有一定的参考价值。

BUG:自定义 View 中实现了 LifecycleObserver 接口,编写了一个 onResume(…) 函数,并给它加上了注解“@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)”,但是所在的 Fragment 还没有处于 onResume() 状态,View 的 onResume(…) 方法就触发了

产生的背景:

  1. 实现了 LifecycleObserver 接口的自定义 View
  2. 自定义 View 中有一个加了 @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) 注解的方法 onResume(…)
  3. 在 MainActivity 中有一个 ViewPager,里面承载了三个 Fragment
  4. 在第三个 Fragment 的布局中使用该自定义 View
  5. 启动应用后发生崩溃,查看错误日志,说 onResume(…) 中使用了未初始化的 ImageView
public class UserHeader extends ConstraintLayout implements LifecycleObserver 
		// ...
    private RoundedImageView roundedImageView;
    // ...
  	public UserHeader(Context context) 
        super(context);
        init(context, null);
    
  	// ...
  	private void init(Context context, AttributeSet attrs) 
        // ...
        // 加载自定义布局
        LayoutInflater.from(context).inflate(R.layout.layout_xxx, this);
      	// ...
        if (getContext() instanceof XXXActivity) 
            ((XXXActivity) getContext()).getLifecycle().addObserver(this);
        
        //实例化组件
        roundedImageView = (RoundedImageView) findViewById(R.id.xxx);
        // ...
    
  
  	@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void onResume() 
        // ...
        if (!TextUtils.isEmpty(userString)) 
            // ...
         else 
            // 发生崩溃的位置
            roundedImageView.setImageResource(mNotLoggedInHeader);
            // ...
        
    

排查过程:

  1. LifeCycle 的 ON_RESUME 触发了,说明其观察的 Context 的 onResume 触发了,控件是写在 Fragment 中,在没有仔细阅读自定义 View 的前提下,天真的认为是因为 Fragment 走了 onResume,导致触发,所以想起 Fragment 懒加载问题,打算去排查(其实 Fragment 要是真的触发了 onResume,那么 roundedImageView 也不会没有初始化了)
  • 检查 Fragment 的生命周期打印,发现并没有执行到 onResume
  • 检查 VP 的 adapter,确实使用了 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 那么说明只有当 VP 切换到第三个 Fragment 时,对应的它的 onResume 才会触发
  1. 既然不是 Fragment 的生命周期导致的 LifeCycle 的 ON_RESUME 触发,那说明调用 addObserver(…) 的对象另有其人,经过查看代码与打印日志,发现是承载 Fragments 的活动 MainActivity,这也不难理解崩溃造成的原因了:
  • 一启动应用,进入 MainActivity 后,它的 onResume 函数就触发了,进而出发了 View 的 onResume(…) 方法。
  • 那为什么在执行 View 的 onResume(…) 方法时 roundedImageView 没有初始化呢,原因在于 addObserver(this) 操作早于 findViewById(…) ,一旦 view 被 addObserver(…) 后,之前产生的事件都会一一触发,直接走了 View 的 onResume(…) 方法,而此时 roundedImageView 的初始化操作还在后面没有执行,先调用了 setImageResource(…) 方法,产生崩溃。

解决方法:

偷了个懒,将 addObserver(…) 操作放在了 findViewById(…) 之后,虽然暂时解决了,但还是存在隐患,万一哪天另外一个同事修改代码的时候,在后面写了初始化方法呢!但是由于是基础库改动需要十分小心而且没有太多时间深入研究,只好写上注释,⚠️警告后人!!日后有时间,要好好考虑一下这个部分的实现了。

以上是关于Android 学习之那些年我们遇到的BUG9:Lifecycle.Event.ON_RESUME 提前触发了的主要内容,如果未能解决你的问题,请参考以下文章

Android 学习之那些年我们遇到的BUG10:No cached version of xxx available for offline mode.

Android 学习之那些年我们遇到的BUG10:No cached version of xxx available for offline mode.

Android学习之相机权限适配问题详解

Java学习之面向对象一

Android开发学习之探究服务

2.Android 学习之虚拟机安装