由于项目的需要,在widget的上要实时刷新图片,而且刷新的频率要随着方向传感器的改变而变化。刷新的频率较高,在正常情况下,无法打开widget对应的应用,提示应用无法响应,从而造成anr的问题。在终端/data/anr/traces.txt中发现异常日志如下:
"main" prio=5 tid=1 Native
|group="main" sCount=1 dsCount=0 obj=0x75d2a930 self=0x7f79e96a00
|sysTid=3524 nice=-10 cgrp=default sched=0/0 handle=0x7f7ef24a98
|state=S schedstat=( 68707806551 28354591632 43974 ) utm=4285 stm=2585 core=0HZ=100
|stack=0x7ffa66c000-0x7ffa66e000 stackSize=8MB
|held mutexes=
kernel: __switch_to+0x7c/0x88
kernel: binder_thread_read+0x45c/0x102c
kernel: binder_ioctl_write_read+0x1c4/0x320
kernel: binder_ioctl+0x2a8/0x6fc
kernel: do_vfs_ioctl+0x4f8/0x5ec
kernel: SyS_ioctl+0x60/0x88
kernel: el0_svc_naked+0x24/0x28
native: #00 pc 000000000006a938 /system/lib64/libc.so (__ioctl+4)
native: #01 pc 000000000001fd60 /system/lib64/libc.so (ioctl+144)
native: #02 pc 0000000000055534 /system/lib64/libbinder.so (_ZN7android14IPCThreadState14talkWithDriverEb+260)
native: #03 pc 0000000000056318 /system/lib64/libbinder.so(_ZN7android14IPCThreadState15waitForResponseEPNS_6ParcelEPi+352)
native: #04 pc 000000000004b1e0 /system/lib64/libbinder.so (_ZN7android8BpBinder8transactEjRKNS_6ParcelEPS1_j+72)
native: #05 pc 00000000000ff3f8 /system/lib64/libandroid_runtime.so (???)
native: #06 pc 000000000089ae38 /system/framework/arm64/boot-framework.oat(Java_android_os_BinderProxy_transactNative__ILandroid_os_Parcel_2Landroid_os_Parcel_2I+196)
atandroid.os.BinderProxy.transactNative(Native method)
atandroid.os.BinderProxy.transact(Binder.java:615)
atcom.android.internal.appwidget.IAppWidgetService$Stub$Proxy.updateAppWidgetProvider(IAppWidgetService.java:744)
atandroid.appwidget.AppWidgetManager.updateAppWidget(AppWidgetManager.java:634)
可以看出其在Binder服务中崩溃了,由于在对应的时间内,还没有完成任务,此时再开启一次服务,从而造成无法响应的问题。
在widget的实时刷新图片,目前想到的方法还是直接传bitmap
RemoteViewsmRemoteCompassView = new RemoteViews(getPackageName(),R.layout.widget_layout);
//获取bitmap而后更新
mRemoteCompassView.setImageViewBitmap(R.id.iv_image, DrawBitmapUtils.getBitmap());
//更新widget
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
appWidgetManager.updateAppWidget(newComponentName(getApplicationContext(), WayPointWidgetProvider.class), mRemoteCompassView);
由于实时刷新,是放在一个监听里面,从而造成这样的问题。
解决方法:
将实时刷新的方法放在一个队列里面,只有当监听里面的任务完成后,才会开始执行下个监听的更新,其流程如下:
Handler mHandler = new Handler();
mHandler.postDelayed(mDataUpdate, 10);
private Runnable mDataUpdate = newRunnable() {
@Override
publicvoid run() {
doTask();
mHandler.postDelayed(mDataUpdate, 50);
}
};
//停止时注销刷新
if(mHandler != null){
mHandler.removeCallbacks(mDataUpdate);
}
这样处理之后,不会造成anr的问题,但建议刷新的频率不要太高,毕竟绑定服务,传输图片还是很耗资源的。