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

Android 从不同线程安全地添加/删除ListView项,android,listview,Android,Listview,在从本地SQLite填充ListView后,我想通过网络从远程数据库获取数据,以便检索新数据,并将其显示在ListView中,以便本地SQLite数据库在没有互联网的情况下只是一种备用方法 我使用不同的线程将网络获取的数据插入SQLite,然后重新填充列表视图列表 当然,应用程序会崩溃,因为在某个时刻,第二个线程正在删除列表中的每一项(以添加新项),而此时,UI线程正在尝试访问已被第二个线程删除的索引 因为这是出于学术目的,所以不使用外部/自定义库,那么不包括自定义库的好方法是什么呢?只更新主应

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

我使用不同的
线程
将网络获取的数据插入SQLite,然后重新填充
列表视图
列表

当然,应用程序会崩溃,因为在某个时刻,第二个
线程
正在删除列表中的每一项(以添加新项),而此时,
UI线程
正在尝试访问已被第二个线程删除的索引


因为这是出于学术目的,所以不使用外部/自定义库,那么不包括自定义库的好方法是什么呢?

只更新主应用程序线程上的
列表视图。例如,不要使用
线程
,而是使用
异步任务
,在
doInBackground()
中执行磁盘和网络I/O,并在
onPostExecute()
中更新
列表视图
。这并不难,因为您已经拥有了数据库。使用IntentService获取网络数据并将其写入内容提供商,而不是编写自己的线程

在活动中,使用游标加载程序在后台从内容提供程序加载数据。CursorLoader包含onDataSetChanged()的实现,因此每次更新内容提供程序时,都会重新加载光标。每次重新加载光标时,将新光标交换到支持ListView的CursorAdapter中

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

  • 将本地广播意图(使用LocalBroadcastManager)从IntentService发送到 网络下载完成时的活动。如果你的活动在前台,它就在前台 将立即获得广播,您可以第一次启动游标加载程序
  • 还要发布来自IntentService的通知。在此通知中,包括内容 意图如果您的活动在后台,并且IntentService已完成,则用户 查看通知。然后,他或她可以单击通知返回您的 活动。如果需要的话,您可以启动游标加载程序,或者直到游标加载程序自动重新启动
您的问题指出,当您在Android中编程时,需要重新思考应用程序结构。Android应用程序不是线性的;它们更像是根据当前状态相互作用的巨型对象。因此,您应该避免在一个活动中编写整个应用程序,或者自上而下编写


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

因为
列表视图中显示的数据是共享的,您必须通过同步来保护它。您应该在不同的线程中编写代码
synchronized(data){//data operation}
,以防崩溃