首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >接手同事的 Android 项目,一运行就崩!LRecyclerView 报 “Observer 未注册”,5 分钟搞定

接手同事的 Android 项目,一运行就崩!LRecyclerView 报 “Observer 未注册”,5 分钟搞定

原创
作者头像
高老师
发布2025-09-17 18:03:10
发布2025-09-17 18:03:10
2580
举报

接手同事的Android项目,一运行就崩!LRecyclerView报“Observer未注册”,5分钟搞定

上周刚接手一个老Android项目,打开代码的瞬间就有点头大——没有Bean类、共用逻辑写得一团乱,更糟的是,一运行Fragment里的LRecyclerView就崩溃,日志里满屏飘着java.lang.IllegalStateException: Observer ... was not registered

查了半小时没头绪,最后跟着源码才发现坑在哪。相信不少Android开发接手旧项目时,都遇到过这种“前人埋坑,后人填坑”的糟心场景,今天把解决过程捋清楚,帮大家少走弯路。

一、先看崩溃日志:关键信息藏在“未注册”里

当时点击切换Fragment,App直接闪退,Logcat里刷出的错误栈里,最扎眼的就是这句:

代码语言:java
复制
java.lang.IllegalStateException: Observer com.github.jdsjlzx.recyclerview.LRecyclerView$DataObserver@97905af was not registered.
at android.database.Observable.unregisterObserver(Observable.java:69)
at android.support.v7.widget.RecyclerView$Adapter.unregisterAdapterDataObserver(RecyclerView.java:6537)
at com.github.jdsjlzx.recyclerview.LRecyclerView.setAdapter(LRecyclerView.java:139)

翻译过来就是“这个Observer没注册过,却要执行取消注册操作”。顺着错误栈定位到LRecyclerView.setAdapter()方法,看了源码才明白问题所在:

LRecyclerView的setAdapter()里有段逻辑:先调用unregisterAdapterDataObserver(mDataObserver)取消旧观察者,再注册新的。但如果第一次设置Adapter时,旧Adapter根本没注册过观察者,这时候执行“取消注册”就会直接崩掉——简单说,就是代码没判断“有没有旧Adapter”,上来就瞎执行取消操作。

再看同事写的代码,发现他在Fragment的onResume()和Handler的handleMessage()里都调用了setAdapter(),相当于每次切换Fragment或收到消息,都重复给LRecyclerView设Adapter,这才触发了重复取消注册的问题。

二、解决思路:设置Adapter前,先判断“有没有旧的”

既然问题出在“重复设置Adapter,且没判断旧Adapter是否存在”,那解决办法就很直接:设置Adapter前,先检查LRecyclerView当前有没有Adapter,只有为空时才新创建并设置

原本同事的代码是这样写的(错误示范):

代码语言:java
复制
// 不管有没有旧Adapter,直接new并设置,导致重复调用setAdapter()
LRecyclerViewAdapter mLRecyclerViewAdapter = new LRecyclerViewAdapter(adapter);
lrecyclerView.setAdapter(mLRecyclerViewAdapter);

这种写法每次执行都会触发LRecyclerView内部的“取消注册-注册”逻辑,第一次执行时旧Observer不存在,直接崩溃。

我把代码改成了这样(正确写法):

代码语言:java
复制
// 关键:先判断当前Adapter是否为空,为空才设置
if (lrecyclerView.getAdapter() == null) {
    // 只在第一次创建时new Adapter并设置
    LRecyclerViewAdapter mLRecyclerViewAdapter = new LRecyclerViewAdapter(adapter);
    lrecyclerView.setAdapter(mLRecyclerViewAdapter);
    // 顺便加了下拉刷新和加载更多的配置(可选,根据需求加)
    lrecyclerView.setRefreshHeader(new MaterialRefreshHeader(getContext()));
    lrecyclerView.setLoadMoreEnabled(true);
}

改完后重新运行,Fragment切换、消息接收时都不再重复设置Adapter,Logcat里的“Observer未注册”错误直接消失,LRecyclerView也能正常加载数据了——前后花了不到5分钟。

三、再深挖一步:为什么会出现这个问题?

后来查了LRecyclerView的官方Issue(源码里也给了链接:https://github.com/jdsjlzx/LRecyclerView/issues/115),发现这是个老坑:

LRecyclerView内部会对传入的Adapter做一层包装(变成LRecyclerViewAdapter),并给包装后的“内部Adapter”注册一个mDataObserver,用来监听数据变化。但它的setAdapter()方法里,会先执行unregisterAdapterDataObserver(mDataObserver)——如果这是第一次设置Adapter,内部Adapter还没注册过这个Observer,就会抛出“未注册”的异常。

而同事的代码里,因为在多个生命周期方法里重复调用setAdapter(),相当于多次触发这个有问题的逻辑,直接把隐藏的bug给暴露了。

四、避坑总结:用LRecyclerView,这2点一定要注意

  1. 别重复设置Adapter:无论是在onResume()onCreateView()还是Handler里,设置Adapter前必须用getAdapter() == null判断,避免重复调用setAdapter()。如果需要更新数据,直接调用adapter.notifyDataSetChanged(),而不是重新new Adapter。
  2. 记得用“包装Adapter”:LRecyclerView要求传入的Adapter必须是LRecyclerViewAdapter(它会包装你的原始Adapter),不能直接传普通的RecyclerView.Adapter,否则会报类型转换错误。正确写法是把原始Adapter传给LRecyclerViewAdapter的构造器:// 原始Adapter MyOriginalAdapter originalAdapter = new MyOriginalAdapter(dataList); // 用LRecyclerViewAdapter包装 LRecyclerViewAdapter wrapperAdapter = new LRecyclerViewAdapter(originalAdapter); // 再设置给LRecyclerView if (lrecyclerView.getAdapter() == null) { lrecyclerView.setAdapter(wrapperAdapter); }

最后再吐槽一句:接手旧项目时,遇到崩溃别慌,先抓准日志里的关键错误(比如这次的“Observer未注册”),顺着错误栈找源码逻辑,很多时候问题都出在“重复调用”“未判断空值”这种小细节上。希望我的踩坑经历,能帮你少花点时间在填坑上~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 接手同事的Android项目,一运行就崩!LRecyclerView报“Observer未注册”,5分钟搞定
    • 一、先看崩溃日志:关键信息藏在“未注册”里
    • 二、解决思路:设置Adapter前,先判断“有没有旧的”
    • 三、再深挖一步:为什么会出现这个问题?
    • 四、避坑总结:用LRecyclerView,这2点一定要注意
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档