【问题标题】:Android - Tracking multiple actions in an IntentServiceAndroid - 在 IntentService 中跟踪多个操作
【发布时间】:2011-11-13 16:12:42
【问题描述】:

我如何跟踪“N”个任务 - 特别是当所有 N 个任务都已完成以及是否有任何任务失败时。

例如,我有一个服务可以响应 5 个独特的 Intent,从远程服务器下载 5 个独特的数据。我还需要一次下载所有 5 条数据。与其复制代码来下载数据,不如启动 5 个 Intent 来下载所有数据,从而利用各个用例。

我遇到的问题是我需要知道所有 5 次下载尝试何时完成。我无法跟踪服务中进行了哪些下载,因为我使用的是 IntentService。 BroadcastReceivers 也存在同样的问题,因为它们仅在其 onReceive 方法期间存在。

我正在查看 sendOrderedBroadcast,但这需要每次下载尝试都有一个 BroadCastReceiver。我也有read 发送完成时会创建结果,但下载完成时不会创建结果?

"如果 resultReceiver 参数不为空,它指定一个 BroadcastReceiver,其 onReceive() 方法将在 发送已排序的广播 Intent 完成。”

也许我可以尝试使用 sendOrederedBroadcast 并在传递的 Intent 中打包某种计数器?

【问题讨论】:

    标签: android asynchronous broadcastreceiver


    【解决方案1】:

    我有一个非常简洁的解决方案,并且似乎不会破坏任何 Android 范例。

    概述 想象一个响应六个动作的 IntentService。其中五个动作下载一些数据,第六个动作是一次下载所有数据的请求。最初的问题是在响应下载所有项目的动作时,如何重用下载五个项目的逻辑。还需要在所有 5 次下载完成后收到通知。

    解决方案 当响应下载所有数据的操作时,IntentService 构造一个 ArrayList,其中包含与服务可以执行的每个下载操作相关的 Intent 字符串。 IntentService 有效地调用自身,传入要执行的下载的 ArrayList。每次服务执行下载时,它都可以“弹出”ArrayList 中的第一个条目,然后再次调用自身。

    ArrayList 不必包含所有 5 个下载,它可以是所有可用下载的子集!每次下载尝试还可以启动任何传达个人成功或失败的意图,而不会中断下载“链”或最终通知的流程。最后,解决这个问题只需要很少的代码。

    protected void onHandleIntent(Intent aIntent) {
            String action = aIntent.getAction();
            // Data the service was called with.
            Bundle incomingData = aIntent.getExtras();
            // Data used to launch any new Intents.
            Bundle outgoingData = new Bundle(); 
            Intent result = null;
    
            if (ACTION_DOWNLOAD_ALL.equals(action)) {
    
                  ArrayList<String> pendingDownloads = new ArrayList<String>();
    
                  // This could contain any number of downloads, does not have to be all 5.
                  pendingDownloads.add(ACTION_DOWNLOAD_1);    
                  pendingDownloads.add(ACTION_DOWNLOAD_2);         
                  pendingDownloads.add(ACTION_DOWNLOAD_3);
                  pendingDownloads.add(ACTION_DOWNLOAD_4);
                  pendingDownloads.add(ACTION_DOWNLOAD_5);
    
                  // This will be the first download in the 'chain' to kick things off.
                  result = new Intent(pendingDownloads.get(0));
    
                  // Add the list of downloads to the Intent
                  outgoingExtras.putStringArrayList("downloads", pendingDownloads);
                  result.putExtras(outgoingExtras);
    
                  // Start the download 'chain'.
                  startService(result);
    
            } 
            else if (ACTION_DOWNLOAD_1.equals(action)) {
                // ... Do download #1.
                processDownloadChain(incomingData);
            }
            else if (ACTION_DOWNLOAD_2.equals(action)) {
                // ... Do download #2.
                processDownloadChain(incomingData);            
            }
            else if (ACTION_DOWNLOAD_3.equals(action)) {
                // ... Do download #3.
                processDownloadChain(incomingData);
            }
            else if (ACTION_DOWNLOAD_4.equals(action)) {
                // ... Do download #4.
                processDownloadChain(incomingData);
            }
            else if (ACTION_DOWNLOAD_5.equals(action)) {
                // ... Do download #5.
                processDownloadChain(incomingData);            
            }
    }
    
    private void processDownloadChain(Bundle incomingData) {
    
            if (incomingData != null) {
    
                // Get the list of downloads.
                ArrayList<String> downloads = incomingData
                        .getStringArrayList("downloads");
    
                if (downloads != null) {
    
                    // Remove the handled download request from the 'chain'.
                    downloads.remove(0);
    
                    if (downloads.size() > 0) {
                        // Have another download request to handle.
                        Intent result = new Intent(downloadIntents.get(0));
                        Bundle outgoing = new Bundle();
    
                        outgoing.putStringArrayList("downloads", downloads);
                        result.putExtras(outgoing);
                        startService(result);
                    } else {
                        // All downloads have been processed.
                        // Could notify BroadcastReceiver here.
                    }
                }
            }
        }
    

    私有方法 processDownloadChain(...) 中的 null 检查允许 IntentService 继续执行各个下载操作,即 IntentService 仍然正常响应下载操作。

    【讨论】:

      【解决方案2】:

      如果你想管理多个线程,使用线程池执行器可能会有所帮助,

      http://developer.android.com/reference/java/util/concurrent/ThreadPoolExecutor.html

      【讨论】:

        【解决方案3】:

        为每个下载请求启动相同的服务,该服务启动一个新的异步任务,该任务在 onPreExecute / onPostExecute & onCancelled 中绑定和解除绑定。

        我不知道您是否可以将服务绑定到自身,如果可以的话会很有趣...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-27
          • 1970-01-01
          • 1970-01-01
          • 2019-11-18
          相关资源
          最近更新 更多