Android HandlerThread Looper可重用吗?

Android HandlerThread Looper可重用吗?,android,android-handler,android-jobscheduler,Android,Android Handler,Android Jobscheduler,我的Android应用程序使用JobService执行我的应用程序小部件刷新 今天,我收到了一份事故报告,内容如下:- 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.r

我的Android应用程序使用JobService执行我的应用程序小部件刷新

今天,我收到了一份事故报告,内容如下:-

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的呢

我想知道的是,以下是一个可接受的解决方案吗? e、 g.重用单个HandlerThread循环器实例

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感到不安。

首先为什么要使用
HandlerThread
?为什么不使用普通的
线程
?您在哪里调用
HandlerThread
上的
quit()
quitsafety()
来关闭它?使用HandlerThread有什么问题?如果我切换到普通线程,我猜我仍然会有同样的问题。我在调用finish job后,突然调用了quit,上面缺少了它,因为我在复制和粘贴代码时丢失了它“使用handlerthread有什么问题?”——使用它没有什么特别的好处。“如果我切换到一个普通线程,我猜我仍然会有同样的问题”--你不应该这样做,因为一旦你的
run()
方法退出,线程就会终止。如果您有500个运行中的
HandlerThread
实例,感觉好像您没有成功调用
quit()
quitsafety()
,这在使用
Thread
@commonware时是不需要的。谢谢您查看我的问题。我接受了你的建议,转而使用“普通”线程来减轻我的工作量。@Hilal:“我应该如何切换到普通线程?”——我无法回答这个问题,因为我不知道你的代码。“他们会从事数据库操作吗?”--会。但是,使用普通螺纹和
HandlerThread
相当过时。现在更流行的是使用反应式框架(
LiveData
、RxJava或Kotlin协同程序)和兼容的数据库访问层(例如Room、SQLDelight)。