将数据从互联网加载到列表视图的最合适方法

Posted

技术标签:

【中文标题】将数据从互联网加载到列表视图的最合适方法【英文标题】:Most appropriate way to load data from internet into listview 【发布时间】:2014-03-24 17:45:13 【问题描述】:

我有一个简单的问题,但最近我一直在思考,但没有一个直接的解决方案。 我有一个列表视图,其中包含来自互联网的加载报价数据。列表项有点复杂,但这不是问题。列表视图使用加载器加载,该加载器从互联网获取报价数据,解析 json 并填充 VO。 VO 列表在适配器中设置,并调用 notifyDataSetChanged 更改,通过适配器的 getView 重新加载列表

现在我在这里使用的模式是:

用户点击一个按钮,我们打开一个片段 片段有LoaderCallbacks,我们在onActivityCreated启动加载器 加载器有一个缓存的线程池执行器(我不能使用异步加载器,因为它们本质上使用线性加载而不是跨 android API 版本并行),它为每个股票创建一个下载工作器。 worker 点击 url 并下载数据,使用 GSON 解析 JSON,创建一个对象并将其放入加载程序的数组列表中。 Lo​​ader 使用一个闩锁等待所有的报价都下载完毕。 一旦完成,就会加载列表。

我的问题是,当列表视图有很多股票时,比如 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 连接类型,而不是移动网络。在移动网络连接中,从流中读取响应需要更长的时间。 【参考方案1】:

对于那些正在阅读本文并遇到类似问题的人,请使用分页“在滚动端加载更多内容”设计,而不是将您的列表分成几部分。 当在 Wifi 或 3G/4G 上时,我结束了使用由缓存线程池执行器支持的完全节流负载,并在任何其他网络上回退到 2 个线程的固定线程池执行器并一次加载 6 个。非常适合我。

【讨论】:

【参考方案2】:

好的,我自己来回答。

没有可行的方法来实现这一点。应用程序设计方法需要将列表大小限制在一个舒适的水平。就我而言,我将重点从 1 个 100-150 只股票的观察名单转移到每个 30 只股票的多个观察名单。由于我不能放弃过滤和排序功能,所以这是唯一可行的方法。

另外需要跟踪网络状态变化并将执行器从缓存调整为单线程。开启 wi-fi 时全力以赴,开启移动网络时显示对话框或 toast 消息。

【讨论】:

以上是关于将数据从互联网加载到列表视图的最合适方法的主要内容,如果未能解决你的问题,请参考以下文章

从互联网加载图像后,Viewpager 不包装内容

颤振:如何在不按按钮的情况下进行列表视图更新?

Android OnItemClick 无法将加载的 SQL 数据库加载到列表视图中

如何在不加载视图的情况下重新加载/刷新部分视图中的级联下拉列表

将数据从父表和子表加载到 DataGridView 的最简单方法,可以进行排序

从互联网加载数据时的进度对话框[重复]