1

我有一个内容提供者,它可以查询多个其他内容提供者(通过内容解析器),并对联系人数据进行一些合并。

基本上我已经扩展了 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);

因此,我创建了 ProviderTask 的 4 个实例,作为 ProviderTask 构造函数的一部分,我传入了一个接口,该接口在我的 callBack 类实例中实现。

class CallBackClass implements MyCallBackIF{}

doInBackground 期间的 ProviderTask 将 ContentResolver.query() 触发到一个提供者。所有 4 个任务都使用相同的提供程序。但是基于 elementId,它通过 onPostExecute() 返回到接口,其中包含它应该放入的游标数组的 elementId(参见下面的**)。

contentProvider 解析传入的 URI,并基于 URI 去向其他 1 个 ContentProvider 查询数据。这可以是本地数据,也可以是来自服务器的远程数据。然后根据来源,它可能会将其与其他数据(本地)合并,并提供一个带有合并数据的新游标。单独的 Content Provider -> Content Resolver -> Content Provider -> Content Resolver 相当快。对于在我们拥有的几个不同应用程序中提供搜索聚合有点有用。提供者确实生成了一个 asyncTask 来加载远程内容提供者数据,并且有一个同步块等待它完成返回数据,然后再返回到 Activity。造成这种情况的部分原因是我可以传入一个有多个提供者要搜索的 uri & 在它触发多个内容解析器查询的地方合并到它自己的合并游标中。(但现在它是一个在异步任务上运行的带有 1 个元素的合并光标)。

** 我正在做的是使用合并游标和 Cursor[] 根据来自各种不同提供者的合并数据更新列表视图。您可能会问,为什么不让内容提供商为我们做这项工作?我们尝试了。它似乎对我们不起作用,但对建议持开放态度。

因此,如果我们的 MergeProvider 查询 - ContentProvider1、ContentProvider2、ContentProvider3、ContentProvider4 和说 ContentProvider3 也必须查询 ContentProvider 1 以合并一些数据。ContentProvider 3 & 4 是远程的(基于服务器)

使用预测搜索,我们希望返回最快的搜索结果首先出现。其他人在他们回来时慢慢加入,如果输入了一个新字母,我们想转储整个结果集,并等待一个新的查询。这就是正在发生的事情,似乎我们在某个地方被阻止了(我们已经尝试提高 AsyncTask 的线程优先级,我们有 ExecuteExecutor w/我们自己的 Executor 和池(将异步任务的最大值提高到 10 到 100)w/没有结果)。

所以有人输入了一个字母“a”——内容提供者 1 和内容提供者 2 会在 0.050 秒内返回。Content Provider 4 会在 0.100 秒后返回。Content Provider 3 在 5.00 秒后返回。(5.00 延迟与我们正在测试的测试服务器有关,但它暴露了我们看到的阻塞问题)。

现在,如果他们继续输入,并且字符串显示 'albert' 它可能已经为 '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)网络上会更加明显。

也许我们不应该为此使用异步任务,而只使用可运行对象?

谢谢。

4

1 回答 1

1

我们没有让我们的应用实现 ContentResolvers 和所有查询,而是将其实现为内容提供者的一部分,并通过 IntentService 分派搜索。

我们将单个游标抓取到临时表,然后使用服务意图,它会触发所有其他内容解析器查询,并填充底层临时表。如果在其中一个意图服务上花费一些时间,则用户不会真正注意到,因为其他意图服务会很快填充它。

似乎解决了我们的问题。

于 2012-12-28T17:21:27.620 回答