Android onHandleIntent IntentService 等待 UI 线程

Posted

技术标签:

【中文标题】Android onHandleIntent IntentService 等待 UI 线程【英文标题】:Android onHandleIntent IntentService waits for UI Thread 【发布时间】:2016-08-24 14:25:50 【问题描述】:

我注意到如果我从 UI 线程调用 startService,直到 UI 线程被释放后才会调用 onHandleIntent。即 onHandleIntent 被 UI 线程阻止。我尝试在 AsyncTask 中调用 startService,但在 UI 线程被释放之前,onHandleIntent 调用仍然被阻塞。 这是 Android 中的一种行为(或错误??)?或者我做错了什么?我正在 android 6.0 中对其进行测试。

这是我的意图服务

public class TestIntentService extends IntentService 

     private static final String TAG = TestIntentService.class.getSimpleName();

     public TestIntentService() 
          super(TAG);
     

     @Override
     protected void onHandleIntent(Intent intent) 
          Log.d(TAG, "onHandleIntent Called");

          try 
               for (int i = 1; i <= 10; i++) 
                   Thread.sleep(1000);
                   Log.d(TAG, "onHandleIntent After " + i + " seconds");
               

               synchronized (MainActivity.handle) 
                    MainActivity.handle.notify();
               

           catch (Exception e) 
               Log.e(TAG, "Exception", e);
          
     

这是我的 Activity 中的方法,单击我正在调用 start Service 的按钮时将调用该方法

protected void onStartServiceButtonClicked(View view) 
    Log.d(TAG, "startServiceClicked");

    Intent intent = new Intent(context,  TestIntentService.class);
    startService(intent);
    Log.d(TAG, "After calling startService");


    synchronized (handle) 
        try 
            Log.d(TAG, "Before waiting");
            handle.wait(4000);
            Log.d(TAG, "After handler Wait");
         catch (InterruptedException e) 
            e.printStackTrace();
        

    

handle只是一个活动类成员变量public static Object handle = new Object();

这是 adb 日志

08-24 10:06:27.777 13564-13564/com.kl.testintentservice D/MainActivity: startServiceClicked
08-24 10:06:27.778 13564-13564/com.kl.testintentservice D/MainActivity: After calling startService
08-24 10:06:27.778 13564-13564/com.kl.testintentservice D/MainActivity: Before waiting
08-24 10:06:31.778 13564-13564/com.kl.testintentservice D/MainActivity: After handler Wait
08-24 10:06:31.782 13564-13564/com.kl.testintentservice I/Choreographer: Skipped 252 frames!  The application may be doing too much work on its main thread.
08-24 10:06:31.783 13564-16520/com.kl.testintentservice D/TestIntentService: onHandleIntent Called
08-24 10:06:32.784 13564-16520/com.kl.testintentservice D/TestIntentService: onHandleIntent After 1 seconds
08-24 10:06:33.784 13564-16520/com.kl.testintentservice D/TestIntentService: onHandleIntent After 2 seconds
08-24 10:06:34.785 13564-16520/com.kl.testintentservice D/TestIntentService: onHandleIntent After 3 seconds
08-24 10:06:35.786 13564-16520/com.kl.testintentservice D/TestIntentService: onHandleIntent After 4 seconds
08-24 10:06:36.786 13564-16520/com.kl.testintentservice D/TestIntentService: onHandleIntent After 5 seconds
08-24 10:06:37.786 13564-16520/com.kl.testintentservice D/TestIntentService: onHandleIntent After 6 seconds
08-24 10:06:38.786 13564-16520/com.kl.testintentservice D/TestIntentService: onHandleIntent After 7 seconds
08-24 10:06:39.787 13564-16520/com.kl.testintentservice D/TestIntentService: onHandleIntent After 8 seconds
08-24 10:06:40.787 13564-16520/com.kl.testintentservice D/TestIntentService: onHandleIntent After 9 seconds
08-24 10:06:41.787 13564-16520/com.kl.testintentservice D/TestIntentService: onHandleIntent After 10 seconds
08-24 10:06:41.787 13564-16520/com.kl.testintentservice D/TestIntentService: handle notified

【问题讨论】:

它不是一个错误,它是一个特性,你没有做错任何事情 【参考方案1】:

这种行为是完全正常的。它不是 IntentService 独有的。任何 startActivity()startService()bindService()sendBroadcast() 调用甚至都不会开始工作,直到您从您所在的任何主应用程序线程回调返回。

由于在回调中占用主应用程序线程超过 1 毫秒是不好的做法,因此这种行为应该不会影响很多开发人员。

【讨论】:

谢谢。我绝对不想阻塞 UI 线程。我的意图是从异步 Intent 服务同步数据。我拥有的服务通过 BLE 获取数据,它是异步的,通常我会在 500 毫秒内取回数据。所以我想看看我是否可以在 UI 线程中最多等待一分钟,这样 UI 组件就不必担心回调,只需在同步调用中获取数据。 UI组件会调用一个facade,facade会等待1秒,如果无法获取数据就会抛出异常。 UI 组件只需要处理异常 @KannanLoganathan:“所以我想看看我是否可以在 UI 线程中最多等待一分钟,这样 UI 组件就不必担心回调,只需在同步调用中获取数据” - 不。首先,您遇到了您在问题中引用的问题。其次,您的 UI 在此期间将完全冻结。第三,如果您将主应用程序线程占用几秒钟,Android 会终止您的应用程序,因为它假定您的应用程序已严重损坏。

以上是关于Android onHandleIntent IntentService 等待 UI 线程的主要内容,如果未能解决你的问题,请参考以下文章

android IntentService生命周期问题

android 四大组件之ServiceIntentService

服务关闭 OnHandleIntent mqtt

使用 IntentService 进行位置监听,但在 onHandleIntent 之后立即调用 onDestroy

handler.postDelayed 在 IntentService 的 onHandleIntent 方法中不起作用

Android IntentService