由服务引起的ANR

时间:2017-10-01 09:18:01

标签: android android-service android-anr-dialog

我有一个启动newSingleThreadScheduledExecutor()的服务。 因此,所有完成的工作都是在工作线程中完成的。 在线程中做的是,从服务器检索一个值,做一些简单的计算并在SharedPreference中保存一个值。

很少,我得到ANR,而log logage告诉我服务造成的 你知道它为什么会发生吗?

此外,如果重要,我有时会重新启动我的服务(停止它,在ScheduledExecutorService上调用shutdownNow(),然后重新启动它。)

这是代码的相关部分。

public void onCreate() {
        sharedPreferences = getSharedPreferences(Constant.SHARED_PREFERENCE, MODE_PRIVATE);
        broadcaster = LocalBroadcastManager.getInstance(this);
        registerReceiver();

        if(scheduler == null) {
            scheduler = Executors.newSingleThreadScheduledExecutor();
            scheduler.scheduleWithFixedDelay
                    (new Runnable() {
                        public void run() {
                            android.util.Log.d(TAG, "globalLogic Scheduler started");
                            globalLogic();
                        }
                    }, 0, CHECK_PERIOD, TimeUnit.HOURS);
        }
    }

3 个答案:

答案 0 :(得分:0)

您应该照顾好Service,因为Service通常会在UIThread中运行:

  

警告:服务在其托管进程的主线程中运行;除非另行指定,否则服务不会创建自己的线程,也不会在单独的进程中运行。如果您的服务要执行任何CPU密集型工作或阻止操作(如MP3播放或网络),则应在服务中创建新线程以完成该工作。通过使用单独的线程,您可以降低应用程序无响应(ANR)错误的风险,并且应用程序的主线程可以保持专用于用户与您的活动的交互。

有3种方法可以解决您的问题:

  1. 使用IntentService
  2. Service
  3. 中使用主题
  4. 或者让您的Service在不同的流程中运行,如下所示:

    <service android:name="com.example.appName" android:process=":externalProcess"/>

  5.   

    如果分配给此属性的名称以冒号(&#39;:&#39;)开头,则在需要时创建一个专用于应用程序的新进程,并且该服务在该进程中运行处理。如果进程名称以小写字符开头,则服务将在该名称的全局进程中运行,前提是它具有此权限。这允许不同应用程序中的组件共享进程,从而减少资源使用。

    您可以阅读有关服务Here

    的更多信息

答案 1 :(得分:0)

尝试在ExecutorService中使用更多主题:

scheduler = Executors.newFixedThreadPool(3);

答案 2 :(得分:0)

为什么你不使用像Firebase JobDispatcher这样的东西? 它效率高,支持API级别9 +。

唯一的限制是它依赖于Google Play服务。

  

<强>要求:   FirebaseJobDispatcher当前依赖于Google Play服务中的计划组件。因此,它不适用于未安装Google Play服务的环境。