从不同的线程安全地添加/删除ListView项

时间:2013-09-16 22:32:10

标签: android listview

从本地ListView填写SQLite后,我想从远程数据库通过网络获取数据,以便检索新数据,并在ListView中显示,以便本地SQLite数据库只是在没有互联网的情况下的后备方法。

我使用不同的Thread将网络获取的数据插入SQLite,然后重新填充ListView列表。

当然,应用程序崩溃是因为在某些时候第二个Thread正在删除列表中的每个项目(添加新项目),当时UI Thread正在尝试访问索引已被辅助线程删除。

由于这是出于学术目的,这个想法不是使用外部/自定义库,那么什么是不包含自定义库的好方法呢?

3 个答案:

答案 0 :(得分:1)

将数据库包装在内容提供商中。不难做到,因为你已经有了数据库。不要编写自己的Thread,而是使用IntentService获取网络数据并将其写入内容提供者。

在您的Activity中,使用CursorLoader在后台加载来自内容提供者的数据。 CursorLoader包含onDataSetChanged()的实现,因此每次更新内容提供程序时,都会重新加载Cursor。每次Cursor重新加载时,将新的Cursor交换到支持ListView的CursorAdapter。

要在IntentService和您的Activity之间进行通信,请执行以下两项操作:

  • 从IntentService发送本地广播Intent(使用LocalBroadcastManager) 网络下载完成时的活动。如果您的活动位于前台,那么 将立即获得广播,并且您可以第一次触发CursorLoader。
  • 同时发布IntentService的通知。在此通知中,包含内容 意图。如果您的Activity在后台并且IntentService完成,则该用户 看到通知。然后,他或她可以单击通知返回到您的 活动。如果需要,可以触发CursorLoader,或者直到CursorLoader自动重启为止。

您的问题指出了在Android中进行编程时重新考虑应用结构的可取性。 Android应用不是线性的;它们更像是根据当前状态相互作用的巨型物体。因此,您应该避免在一个活动中编写整个应用程序,或者从上到下编写它。

此外,几乎没有理由自己创建一个新的Thread()。 Android提供了大量可以为您处理异步处理的类。如果您发现自己编写了Thread()或run(),请小心。

答案 1 :(得分:0)

仅更新主应用程序线程上的ListView。例如,使用Thread代替AsyncTask,在doInBackground()中执行磁盘和网络I / O并更新ListView中的onPostExecute()

答案 2 :(得分:0)

由于ListView中显示的数据是共享的,因此您必须通过同步保护它。您应该在崩溃的情况下在不同的线程中编写代码synchronized (data) {// data operation}