1.布局中Pag不显示的问题
在调查一个pag不显示的问题,整体逻辑没有问题,但是就是不显示
pag不显示的根本原因大概有文件找不到,一个是路径问题,一个是配置文件的问题
PAGFile.Load(context.getAssets(),"abc.png")
这个一般不会是路径问题,因为,context,getAssets()就是assets目录下去找了,除非你的代码是这样写的
PAGFile.Load(context.getAssets(),"../abc.pag")
这样应该就找不到了
我这个问题是多渠道包的问题,我有2个渠道一个是A渠道,一个是B渠道,我的资源放在了A
渠道的assets下面,但是如果多渠道没有配置的话,他默认是找main/assets的
但是main/assets里面并没有我的abc.pag,所以就不能显示
最终重新配置渠道就解决了,如下:
sourceSets {
A {
assets.srcDirs "src/main/assets", "src/A/assets"
}
}
2.数据库降级问题
android.database.sqlite.SQLiteException,Can't downgrade database from version 25 to 24
数据库问题,不能降级,要升级,否则直接崩溃。
3.RecycleView 列表滑动卡顿
背景是这样的,我使用的这个列表主要是加载图片,一开始几张图片并没有卡顿,当我添加了几个上百张之后滑动出现卡顿。通过trace分析,发现一帧干了300多ms,正常60HZ的屏幕一帧也就是 1000ms ÷ 60 ≈ 16.67 毫秒(ms)。所以还是APP自身的问题。
从代码上看没有任何问题,Glide.with加载图片,其余Glide之外的操作也没有耗时,没有任何头绪。
紧接着我通过top命令查看CPU占用率发现当我滑动的时候,当前应用的CPU占用率非常高,手指停止之后,CPU占用率就恢复正常了,这证明滑动的过程中一直吃在系统资源,所以我再次开始分析,只有Glide这里有对bitmap加载图片的处理,代码如下:
Glide.with(imageView.getContext())
.load(url)
.override(targetWidth, targetHeight)
.centerCrop()
.error(R.drawable.logd_err)
.into(imageView);
上面这串代码是在ListAdapter中的onBinderViewHolder()当我们滑动列表的时候,onBinderViewHolder会不断的加载图片,导致频繁的执行压缩Bitmap导致占用内存。所以直接将 override(targetWidth, targetHeight) 删掉就可以了。
3.new Thread() 优化
当我们new Thread 中有少量操作,可以快速释放,那这个Thread相对来说还是可以的,但是如果频繁的创建Thread就不太好。我们可以用HandlerThread 来替代new Thread。HandlerThread 是串行的消息队列,而new Thread 并行的线程消息。HandlerThread 创建一个线程,可以减少一定的开销。具体的写法如下:
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
// 获取 HandlerThread 的 Looper 并创建 Handler
Handler handler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
// 处理消息
performTask(msg);
}
};
// 发送消息到 HandlerThread
Message message = handler.obtainMessage();
message.what = 1;
handler.sendMessage(message);
private void performTask(Message msg) {
// 执行耗时操作
}
5.RemoteCallbackList
异常信息:
java.lang.IllegalStateException: beginBroadcast() called while already in a broadcast
这个异常 java.lang.IllegalStateException: beginBroadcast() called while already in a broadcast 是由于 RemoteCallbackList 的广播过程没有正确收尾 导致的,具体分析和解决方案如下:
一、异常原因解析
RemoteCallbackList 是 Android 提供的用于管理跨进程回调的工具类,其核心作用是安全地遍历和触发注册的回调(尤其是跨进程场景)。它有两个关键方法:
beginBroadcast():开始遍历回调列表,获取当前回调数量(返回值为回调总数),此时列表会被「锁定」,防止遍历过程中回调被移除导致异常。
finishBroadcast():结束遍历,解锁列表,允许后续的回调添加 / 移除操作。
异常触发条件:当 beginBroadcast() 被调用时,如果上一次的广播(beginBroadcast() 之后)没有通过 finishBroadcast() 收尾,就会抛出此异常 —— 因为 RemoteCallbackList 不允许嵌套的广播过程(同一时间只能有一个活跃的广播)。
// 错误示例:缺少 finishBroadcast()
RemoteCallbackList<MyCallback> mCallbacks = new RemoteCallbackList<>();
new Thread(new Runnable() {
@Override
public void run() {
int count = mCallbacks.beginBroadcast(); // 第928行附近
for (int i = 0; i < count; i++) {
MyCallback callback = mCallbacks.getBroadcastItem(i);
// 触发回调...
}
// 遗漏了 finishBroadcast()!导致下次 beginBroadcast() 失败
}
}).start();
// 正确示例:begin 和 finish 成对出现,用 try-finally 确保收尾
RemoteCallbackList<MyCallback> mCallbacks = new RemoteCallbackList<>();
new Thread(new Runnable() {
@Override
public void run() {
int count = mCallbacks.beginBroadcast(); // 对应第928行
try {
// 遍历回调并触发
for (int i = 0; i < count; i++) {
MyCallback callback = mCallbacks.getBroadcastItem(i);
// 执行回调逻辑(例如 callback.onUserChanged())
}
} finally {
// 必须调用 finishBroadcast() 结束广播,释放锁定
mCallbacks.finishBroadcast();
}
}
}).start();
如果只添加了 finally { mCallbacks.finishBroadcast() } 但没有加同步锁,仍然可能出现 beginBroadcast() called while already in a broadcast 异常。
原因如下:
RemoteCallbackList 的 beginBroadcast() 和 finishBroadcast() 本身不是线程安全的。即使你保证了单次广播过程中 begin 和 finish 成对成对(通过 try-finally),但如果有多个线程同时调用广播逻辑,就可能出现以下场景:
线程 A 调用 beginBroadcast() 成功(此时广播状态被标记为「活跃」);
线程 B 在线程 A 未调用 finishBroadcast() 前,也调用 beginBroadcast();
线程 B 检测到已有活跃的广播,直接抛出 IllegalStateException。
简言之:try-finally 只能保证「单次广播的开始和结束成对出现」,但无法阻止「多个线程同时发起广播」,而 RemoteCallbackList 不允许并发广播(同一时间只能有一个广播过程)。
结论
必须加同步锁:通过 synchronized 等机制确保同一时间只有一个线程执行广播逻辑(从 beginBroadcast() 到 finishBroadcast() 的完整过程)。
try-finally 是基础:保证即使广播过程中出现异常,finishBroadcast() 也会执行,避免永久锁死广播状态。
两者缺一不可,才能彻底避免该异常。