【发布时间】:2012-05-14 02:28:03
【问题描述】:
我有一个内容提供者,它可以查询多个其他内容提供者(通过内容解析器),并对联系人数据进行一些合并。
基本上我已经扩展了 asyncTask 并处理了数据。在我的主 UI 线程中,我执行以下操作
cancelAllExistingTask();
proiverTest1 = new ProviderTask(getActivity, MyActivity.this.callBack).execute(SearchString, elementId1);
proiverTest2 = new ProviderTask(getActivity, MyActivity.this.callBack).execute(SearchString, elementId2);
proiverTest3 = new ProviderTask(getActivity, MyActivity.this.callBack).execute(SearchString, elementId3);
proiverTest4 = new ProviderTask(getActivity, MyActivity.this.callBack).execute(SearchString, elementId4);
所以我创建了 4 个 ProviderTask 实例,作为 ProviderTask 构造函数的一部分,我传入了一个在我的 callBack 类实例中实现的接口。
class CallBackClass implements MyCallBackIF{}
doInBackground 期间的 ProviderTask 触发 ContentResolver.query() 到 ONE 提供者。所有 4 个任务都使用相同的提供程序。但是基于 elementId,它通过 onPostExecute() 返回到接口,其中包含它应该放入的游标数组的 elementId(参见下面的**)。
contentProvider 解析传入的 URI,并根据 URI 向其他 1 个 ContentProvider 查询数据。这可以是本地数据,也可以是来自服务器的远程数据。然后根据来源,它可能会将其与其他数据(本地)合并,并提供一个带有合并数据的新游标。单独的 Content Provider -> Content Resolver -> Content Provider -> Content Resolver 相当快。对于在我们拥有的几个不同应用程序中提供搜索聚合有点有用。提供者确实生成了一个 asyncTask 来加载远程内容提供者数据,并且有一个同步块等待它完成返回数据,然后再返回到 Activity。造成这种情况的部分原因是我可以传入一个 uri,该 uri 有多个提供者进行搜索和合并,它会将多个内容解析器查询触发到它自己的合并游标中。 (但现在它是一个在异步任务上运行的带有 1 个元素的合并光标)。
** 我正在做的是使用合并游标和 Cursor[] 根据来自各种不同提供者的合并数据来更新列表视图。您可能会问,为什么不让内容提供商为我们做这项工作?我们尝试了。它似乎对我们不起作用,但欢迎提出建议。
因此,如果我们的 MergeProvider 查询 - ContentProvider1、ContentProvider2、ContentProvider3、ContentProvider4 和 ContentProvider3 也必须查询 ContentProvider 1 以合并一些数据。 ContentProvider 3 & 4 是远程的(基于服务器)
W/ 预测搜索我们希望返回最快的搜索结果首先出现。其他人在他们回来时慢慢加入,如果输入了一个新字母,我们想转储整个结果集,并等待一个新的查询。这就是正在发生的事情,似乎我们在某个地方被阻止了(我们已经尝试提高 AsyncTask 的线程优先级,我们有 ExecuteExecutor w/我们自己的 Executor 和池(将异步任务的最大值提高到 10 到 100)w/没有结果)。
所以有人输入了一封信 'a' - 内容提供者 1 和内容提供者 2 在 0.050 秒内返回。 Content Provider 4 会在 0.100 秒后返回。 Content Provider 3 在 5.00 秒后返回。 (5.00 延迟与我们正在测试的测试服务器有关,但它暴露了我们看到的阻塞问题)。
现在如果他们继续输入,并且字符串显示 “阿尔伯特” 它可能已经为 'al' 启动了一个新的 AsyncTask,其中一些快速返回,而另一些则没有。假设 Provider 3 仍在等待响应。如果预测搜索在结果时发生变化,我们的代码将丢弃结果回来。 (这很好)。 所以它会触发另一轮 AsyncTasks 'albert'。现在记住 Provider 3 在它的 5 秒响应中仍然关闭。
我们在 AsyncTask 和 Calling 方法(处理程序)中添加了一些日志记录。 我们看到的是 AsyncTask 正在创建,但在 SearchProvider3 返回结果(并且它们被丢弃)之前,我们没有看到 doInBackground() 开始。我很困惑为什么会这样。但它基本上阻塞了其他 AsyncTask 对象。不知道什么会导致 doInBackground() 在另一个 AsyncTask 返回之前不会被调用,除非它是因为 10 个 AsyncTask 的最大限制?使用我们自己的 ThreadPoolExecutor 实现(甚至创建两个不同的 ThreadPoolExecutor 实例),我们仍然看到相同的问题。
如果在我们的 Provider 3 的查询方法中添加一个 thread.sleep(60000),这是非常明显的。基本上看起来可能有 5 个异步任务在开始阻塞之前被调用。我们的目标是独立于其他长时间运行的任务,更快地获得本地匹配结果。这在慢速 (3g) 网络上会更加明显。
也许我们不应该为此使用异步任务,而只使用可运行对象?
谢谢。
【问题讨论】:
标签: android multithreading android-asynctask android-contentprovider