AndroidAutoSize
AndroidAutoSize copied to clipboard
AutoSize1.2.1版本导致线程调度抛异常Not in applications main thread
autosize/src/main/java/me/jessyan/autosize/utils/Preconditions.java中checkMainThread方法的调用导致线程异常,使用Thread或rxJava等线程,执行部分操作会触发"Not in applications main thread"异常。
具体表现: 1.Thread中进行下载并更新通知栏下载进度,下载完成后设置通知栏完成状态点击可安装,这时就会抛出IllegalStateException"Not in applications main thread",完成通知消息无法显示并无法弹出系统安装; 2.
private void setQRImage(String qrcodeString, ImageView mQrcodeImage, boolean isCicle) {
if (TextUtils.isEmpty(qrcodeString)) return;
Observable.create(new Observable.OnSubscribe<Bitmap>() {
@Override
public void call(Subscriber<? super Bitmap> subscriber) {
Bitmap bitmap;
try {
int size = (int) Utils.dpTopx(255f);
bitmap = QRCodeUtil.creatQrCode(qrcodeString, size, size, BitmapFactory.decodeResource(mQrcodeImage.getContext().getResources(), R.mipmap.app_icon), 0);
subscriber.onNext(!isCicle ? bitmap : BitmapUitl.drawRoval(BitmapUitl.ALL, bitmap));
} catch (WriterException e) {
e.printStackTrace();
subscriber.onError(e);
}
subscriber.onCompleted();
}
}).compose(TransformUtils.<Bitmap>defaultSchedulers())
.subscribe(new Observer<Bitmap>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Bitmap bitmap) {
mQrcodeImage.setImageBitmap(bitmap);
}
});
}
以上代码生成二维码,同样抛出IllegalStateException"Not in applications main thread"
3.同上使用RxJava call中使用Glide.get()方法获取Bitmap,调用两次时同样会抛出异常
4.使用友盟分享SDK进行小程序、单图分享功能,当图片为本地图片时无法进行分享,查看友盟SDK相关代码,同样使用了线程获取本地图片,获取时抛异常导致;
解决:
public static void checkMainThread() {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("Not in applications main thread");
}
}
不应该抛异常,调整成返回值供外部调用即可
public static boolean checkMainThread() {
return Looper.myLooper() == Looper.getMainLooper();
}
能把错误信息栈贴出来吗
我这边报了同样的错误,应该是判断主线程抛出异常导致 java.lang.IllegalStateException: Not in applications main thread at me.jessyan.autosize.utils.Preconditions.checkMainThread(Preconditions.java:113) at me.jessyan.autosize.AutoSizeCompat.autoConvertDensity(AutoSizeCompat.java:139) at me.jessyan.autosize.AutoSizeCompat.autoConvertDensityBaseOnWidth(AutoSizeCompat.java:112) at me.jessyan.autosize.AutoSizeCompat.autoConvertDensityOfGlobal(AutoSizeCompat.java:57) at com.jee.common.base.BaseActivity.getResources(BaseActivity.kt:123) at com.android.internal.policy.DecorContext.getResources(DecorContext.java:90) at android.view.ViewRootImpl.isShouldDelayMsg4SeamlessLauncher(ViewRootImpl.java:8384) at android.view.ViewRootImpl.dispatchResized(ViewRootImpl.java:8374) at android.view.ViewRootImpl.access$5200(ViewRootImpl.java:168) at android.view.ViewRootImpl$W.resized(ViewRootImpl.java:9913) at android.view.IWindow$Stub.onTransact(IWindow.java:358) at android.os.Binder.execTransactInternal(Binder.java:1028) at android.os.Binder.execTransact(Binder.java:1001)
我在外面加了主线程判断之后运行正常, override fun getResources(): Resources { if ( Looper.myLooper() == Looper.getMainLooper()) { AutoSizeCompat.autoConvertDensityOfGlobal(super.getResources()) } return super.getResources() }
能把错误信息栈贴出来吗
https://github.com/JessYanCoding/AndroidAutoSize/issues/359#issuecomment-871054381
@1Ezreal 在调用 autoConvertDensityOfGlobal 的地方切换到主线程再调用 at com.jee.common.base.BaseActivity.getResources(BaseActivity.kt:123)
设置 Density 和 获取 Density 如果不在同一个线程,有可能会造成 UI 代码获取到的 Density 不是最新设置的 Density,导致程序未能按预期计划去执行而适配异常,如果不抛异常,开发人员会极难发现这个问题,以及捕捉适配异常的原因,所以抛异常是为了让开发人员在开发阶段就能定位这个问题,从而做出相应的处理,如果不抛异常,崩溃虽然不会发生,但是会把一个隐患暴露在你的生产环境
设置 Density 和 获取 Density 如果不在同一个线程,有可能会造成 UI 代码获取到的 Density 不是最新设置的 Density,导致程序未能按预期计划去执行而适配异常,如果不抛异常,开发人员会极难发现这个问题,以及捕捉适配异常的原因,所以抛异常是为了让开发人员在开发阶段就能定位这个问题,从而做出相应的处理,如果不抛异常,崩溃虽然不会发生,但是会把一个隐患暴露在你的生产环境
嗯,确实如此,我在Activity基类里
@Override
public Resources getResources() {
AutoSizeCompat.autoConvertDensity(super.getResources(), getSizeInDp(), isBaseOnWidth());
return super.getResources();
}
中会抛异常,增加线程判断后,则全都正常,同时也可以避免Density不是最新的风险。
@Override
public Resources getResources() {
if (Looper.myLooper() == Looper.getMainLooper()) {
AutoSizeCompat.autoConvertDensity(super.getResources(), getSizeInDp(), isBaseOnWidth());
}
return super.getResources();
}
虽然得增加一行代码,但1.2.1版本的优化,我是同意的。
是转主线程执行好一点还是直接判断会好一点呢
我这样子弄好像也没问题 CoroutineScope(Dispatchers.Main).launch { AutoSizeCompat.autoConvertDensityOfGlobal(super.getResources()) }
最好还是切主线程调用,保证 Density 随时都能同步更新
设置 Density 和 获取 Density 如果不在同一个线程,有可能会造成 UI 代码获取到的 Density 不是最新设置的 Density,导致程序未能按预期计划去执行而适配异常,如果不抛异常,开发人员会极难发现这个问题,以及捕捉适配异常的原因,所以抛异常是为了让开发人员在开发阶段就能定位这个问题,从而做出相应的处理,如果不抛异常,崩溃虽然不会发生,但是会把一个隐患暴露在你的生产环境
嗯,确实如此,我在Activity基类里
@Override public Resources getResources() { AutoSizeCompat.autoConvertDensity(super.getResources(), getSizeInDp(), isBaseOnWidth()); return super.getResources(); }中会抛异常,增加线程判断后,则全都正常,同时也可以避免Density不是最新的风险。
@Override public Resources getResources() { if (Looper.myLooper() == Looper.getMainLooper()) { AutoSizeCompat.autoConvertDensity(super.getResources(), getSizeInDp(), isBaseOnWidth()); } return super.getResources(); }虽然得增加一行代码,但1.2.1版本的优化,我是同意的。
这个解决了我的问题