我的Android应用使用JobService来执行我的App Widget Refresh。
今天我收到了一份崩溃报告: -
Fatal Exception: java.lang.OutOfMemoryError: Could not allocate JNI Env
at java.lang.Thread.nativeCreate(Thread.java)
at java.lang.Thread.start(Thread.java:731)
at com.research.app_widget.WidgetUpdateJobService.onStartJob(SourceFile:29)
at android.app.job.JobService$JobHandler.handleMessage(JobService.java:143)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
从崩溃的堆栈跟踪中,我创建了500多个HandlerThread实例
我的onStartJob方法类似于: -
@Override
public boolean onStartJob(final JobParameters params) {
mServerHandlerThread = new HandlerThread("ServerApplication");
mServerHandlerThread.start();
mServerHandler = new Handler(mServerHandlerThread.getLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(final Message msg) {
final int what = msg.what;
switch (what) {
case WHAT_WIDGET_REFRESH:
refreshWidget(params);
break;
default:
Log.e(TAG, "handleMessage: Unexpected WHAT = " + what);
}
return true;
}
});
mServerHandler.sendEmptyMessage(WHAT_WIDGET_REFRESH);
return true;
}
refreshWidget(params)方法如下: -
private void refreshWidget(final JobParameters params) {
final PersistableBundle persistableBundle = params.getExtras();
final int[] appWidgetIds = persistableBundle.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
if (appWidgetIds == null) {
Log.e(TAG, "refreshWidget: appWidgetIds array is null");
} else {
for (int appWidgetId : appWidgetIds) {
new WidgetRemoteViewsHelper().configureViews(this.getApplicationContext(), appWidgetId, isListEmpty(persistableBundle));
}
}
jobFinished(params, false);
}
我不明白的是Android启动了100个scheduledJobs的限制,那么我如何设法启动超过500个HandlerThreads?
我想知道的是,以下是可接受的解决方案吗? 例如重用一个HandlerThread Looper实例?
private final HandlerThread mServerHandlerThread;
{
mServerHandlerThread = new HandlerThread("ServerApplication");
mServerHandlerThread.start();
}
@Override
public boolean onStartJob(final JobParameters params) {
mServerHandler = new Handler(mServerHandlerThread.getLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(final Message msg) {
final int what = msg.what;
switch (what) {
case WHAT_WIDGET_REFRESH:
refreshWidget(params);
break;
default:
Log.e(TAG, "handleMessage: Unexpected WHAT = " + what);
}
return true;
}
});
mServerHandler.sendEmptyMessage(WHAT_WIDGET_REFRESH);
return true;
}
从我的测试到目前为止,这种方法似乎按要求工作。我只是对重复使用一个HandlerThread感到不安。