【发布时间】:2014-03-24 17:45:13
【问题描述】:
我有一个简单的问题,但最近我一直在思考,但没有一个直接的解决方案。
我有一个列表视图,其中包含来自互联网的加载报价数据。列表项有点复杂,但这不是问题。列表视图使用加载器加载,该加载器从互联网获取报价数据,解析 json 并填充 VO。 VO 列表在适配器中设置,并调用 notifyDataSetChanged 更改,通过适配器的 getView 重新加载列表
现在我在这里使用的模式是:
- 用户点击一个按钮,我们打开一个片段
- 片段有
LoaderCallbacks,我们在onActivityCreated启动加载器 - 加载器有一个缓存的线程池执行器(我不能使用异步加载器,因为它们本质上使用线性加载而不是跨 Android API 版本并行),它为每个股票创建一个下载工作器。
- worker 点击 url 并下载数据,使用 GSON 解析 JSON,创建一个对象并将其放入加载程序的数组列表中。
- Loader 使用一个闩锁等待所有的报价都下载完毕。
- 一旦完成,就会加载列表。
我的问题是,当列表视图有很多股票时,比如 70 到 90,报价下载过程会变慢。在直接 wifi 网络上,列表加载大约需要 1.5 到 2 秒。在 2G 和 3G 以及混合网络等移动数据网络上,加载大约需要 30-40 秒。分析显示大部分时间花在从流中读取数据上。每个报价 URL 命中大约 700-800 字节,加载大约需要 800-900 毫秒。我正在使用HttpURLConnection 加载网址。
我不能在列表中使用动态加载模式,因为我有菜单项来过滤和排序列表视图。如果我们一开始就没有列表中的所有报价数据,它们就没有任何意义。
有没有更好的方法来做到这一点?我已经阅读了周围的东西,并尝试了“当该行在屏幕上可见时,列表中每一行的新异步任务”但不能使用它,因为这意味着延迟加载数据。
编辑以显示数据是如何反序列化的:
InputStream inputstreamObj = (InputStream) conn.getContent();//getInputStream();
if(inputstreamObj != null){
Reader reader = new InputStreamReader(inputstreamObj);
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(List.class, new CompanyCorpAnnouncementsVODeserializer());
Gson gson = gsonBuilder.create();
retVal = gson.fromJson(reader, List.class);
}
【问题讨论】:
-
我认为的另一件事是将下载的 JSON 保存在 SQLITE DB 中,并在片段加载时加载它们。然后,当加载程序再次下载新数据时,将该数据放入 Db 并更新列表视图。但这只是解决问题的蹩脚解决方法,根本无法解决问题。
-
我没看错吧,您正在下载 70-90 个报价 x 800kbs 每个股票报价?
-
抱歉弄错了。它大约 700-800 字节......不是 kbs 用这个问题更新了问题。
-
是否可以将请求卸载到服务器,然后在完成后下载整个项目?对于每台设备,这可能有助于减少大量开销。
-
@MichaelTodd:我已经试过了。通过将大约 2 到 3 只股票组合在一个“获取报价命中”中,我可以减少命中(或锯齿线程)的数量,但有效负载大小大致仍然相同,除了没有再次发送的标头的几个字节。这种方法实际上更好地帮助了 wifi 连接类型,而不是移动网络。在移动网络连接中,从流中读取响应需要更长的时间。
标签: java android listview android-listview