IntentServices 和 AsyncTasks 之间的同步
Synchronizing between IntentServices and AsyncTasks
这建立在 之上,这是一个 PoC。
上图显示了我的应用程序的基本设置。
在实时应用程序中,我在 Fragment
的 onOptionsItemSelected()
方法中调用 IntentService
,如下所示:
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
...
...
Intent myServiceIntent = new Intent(getActivity(), MyService.class);
getActivity().startService(myServiceIntent);
...
...
}
MyService
从云端下载数据并将其保存到本地 SQLite
数据库中。接下来,同一个 Fragment
中的 AsyncTask
消耗数据以更新另一个 Fragment
。关键是,AsyncTask
应该在 MyService
完成后开始他们的 doInBackground()
。
与 Service
配合得很好,显示 ProgressBar
并保持 UI 通过 BroadcastReceiver
不断更新中间结果。请注意 Service
是从 AppCompatActivity
调用的,但在实际应用中,它是从 Fragment
调用的。完全相同的设置失败,没有 ProgressBar
,没有临时更新。来自 BroadcastReceiver
的日志消息显示 在 AsyncTask
完成后。
接下来的问题是,
IntentService
是否天生会像 AsyncTask
get()
那样阻塞 UI? PoC 答案是否定的,但在我的实时应用程序中,临时进度更新失败。
AsyncTask
如何等到 IntentService
完成?
- 为什么
BroadcastReceiver
中的日志仅在 AsyncTask
完成后才显示 ?
- 这种情况很常见,是否有克服此问题的最佳做法?
请原谅我的冗长,但希望情况清楚。如果有歧义,请发表评论。
请注意,我看过 this answer 等等,但不幸的是 none 真的很适合我。
非常感谢!
Do IntentServices block UI by nature, like AsyncTask get()?
不,他们没有,这就是 IntentService 在后台做事的全部意义
How can an AsyncTask wait till an IntentService has finished?
有几种方法,但一种简单的方法是在您的 activity 中使用 BroadcastReceiver 来保存您的片段并让您的 activity 触发 fragment/s 更新。请记住,一个片段不应与另一个片段对话,您的 activity 应该是片段之间的委托信息。
为什么您的 BroadcastReceiver 在您的真实应用程序中不起作用我无法回答您提供的信息,因为您在更改它时可能只是遗漏了一些东西。我一直将 BroadcastReceivers 与 IntentServices 一起使用,没有任何问题
感谢@tyczj 简洁明了的回答!
正式完成...
Why are logs in the BroadcastReceiver
displayed only after the AsyncTasks
have finished?
虽然晦涩难懂,但这是我的错误,呃。 (仅)调试显示。
This being such a common situation, is there a best practice to overcome this?
最佳实践恕我直言,实践。然而,这些是我理解的要点(困难的方式):
IntentService
超过 AsyncTask
后台工作超过 5 秒
LocalBroadcastManager
和 BroadcastReceiver
以显示来自 IntentService
的进度更新并让其他更快的后台线程等待。
这建立在
上图显示了我的应用程序的基本设置。
在实时应用程序中,我在 Fragment
的 onOptionsItemSelected()
方法中调用 IntentService
,如下所示:
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
...
...
Intent myServiceIntent = new Intent(getActivity(), MyService.class);
getActivity().startService(myServiceIntent);
...
...
}
MyService
从云端下载数据并将其保存到本地 SQLite
数据库中。接下来,同一个 Fragment
中的 AsyncTask
消耗数据以更新另一个 Fragment
。关键是,AsyncTask
应该在 MyService
完成后开始他们的 doInBackground()
。
Service
配合得很好,显示 ProgressBar
并保持 UI 通过 BroadcastReceiver
不断更新中间结果。请注意 Service
是从 AppCompatActivity
调用的,但在实际应用中,它是从 Fragment
调用的。完全相同的设置失败,没有 ProgressBar
,没有临时更新。来自 BroadcastReceiver
的日志消息显示 在 AsyncTask
完成后。
接下来的问题是,
IntentService
是否天生会像AsyncTask
get()
那样阻塞 UI? PoC 答案是否定的,但在我的实时应用程序中,临时进度更新失败。AsyncTask
如何等到IntentService
完成?- 为什么
BroadcastReceiver
中的日志仅在AsyncTask
完成后才显示 ? - 这种情况很常见,是否有克服此问题的最佳做法?
请原谅我的冗长,但希望情况清楚。如果有歧义,请发表评论。
请注意,我看过 this answer 等等,但不幸的是 none 真的很适合我。
非常感谢!
Do IntentServices block UI by nature, like AsyncTask get()?
不,他们没有,这就是 IntentService 在后台做事的全部意义
How can an AsyncTask wait till an IntentService has finished?
有几种方法,但一种简单的方法是在您的 activity 中使用 BroadcastReceiver 来保存您的片段并让您的 activity 触发 fragment/s 更新。请记住,一个片段不应与另一个片段对话,您的 activity 应该是片段之间的委托信息。
为什么您的 BroadcastReceiver 在您的真实应用程序中不起作用我无法回答您提供的信息,因为您在更改它时可能只是遗漏了一些东西。我一直将 BroadcastReceivers 与 IntentServices 一起使用,没有任何问题
感谢@tyczj 简洁明了的回答!
正式完成...
Why are logs in the
BroadcastReceiver
displayed only after theAsyncTasks
have finished?
虽然晦涩难懂,但这是我的错误,呃。 (仅)调试显示。
This being such a common situation, is there a best practice to overcome this?
最佳实践恕我直言,实践。然而,这些是我理解的要点(困难的方式):
IntentService
超过AsyncTask
后台工作超过 5 秒LocalBroadcastManager
和BroadcastReceiver
以显示来自IntentService
的进度更新并让其他更快的后台线程等待。