我一直在努力解决这个问题。在我的项目中,有几个活动包括ListView和扩展BaseAdapter的自定义适配器。它们还实现了一些通常会通知它数据已被更改的接口。
但是,当我从我的类中实现的listener / interface方法调用notifyDataSetChanged()时,ListView不会更新,也不会调用任何适配器方法(getCount(),getView())。
我知道这与调用notifyDataSetChanged()的事实有关,我的意思是哪个线程,但我不太明白它,也找不到这种行为的简单解释。
作为这个问题的解决方法,我使用一个定期调用方法的Handler,在该方法中,我查看布尔值'needsToBeUpdated'值是否为true,然后调用notifyDataSetChanged()方法。但这很难看,而且我确信需要有一种异步方式。
任何帮助都将不胜感激。
我正在谈论的伪代码:
public class FriendsActivity extends Activity implements FriendsListener {
private ListView mListView;
private ArrayList<Friends> mFriendsList;
private FriendsAdapter mFriendsAdapter;
private boolean mNeedsToBeUpdated;
private Handler mListUpdateHandler;
private Runnable mListUpdateTask;
onCreate() {
initViews();
mFriendsAdapter = new FriendsAdapter(mFriendsList);
mListView.setAdapter(mFriendsAdapter);
SomeStaticClass.addFriendListener(this)
mNeedsToBeUpdated = false;
mListUpdateHandler = new Handler();
mListUpdateHandler.removeCallbacks(mListUpdateTask);
mListUpdateHandler.postDelayed(mListUpdateTask, 10000);
}
onListenerMethod() {
updateFriendsList();
mFriendsAdapter.updateDataSource(mFriendsList);
mFriendsAdapter.notifyDataSetChanged(); // THIS DOESN'T UPDATE THE VIEWS
mNeedsToBeUpdated = true;
}
protected void onResume() {
mListUpdateTask = new Runnable() {
public void run() {
if (mNeedsToBeUpdated ) {
updateFriendsList();
mFriendsAdapter.updateDataSource(mFriendsList);
mFriendsAdapter.notifyDataSetChanged(); // THIS UPDATES THE VIEWS
mListsRequireUpdating = false;
}
mListUpdateHandler.postDelayed(mListUpdateTask, 10000);
}
};
mListUpdateHandler = new Handler();
mListUpdateHandler.removeCallbacks(mListUpdateTask);
mListUpdateHandler.post(mListUpdateTask);
super.onResume();
}
编辑:当我在这里发布这个文章时,我几乎没有时间找到答案......
我讨厌这样做,但我付出了更多的努力来寻找答案,我想我发现它归功于此:http://developer.android.com/resources/articles/painless-threading.html - 而且:http://developer.android.com/reference/android/os/Handler.html
解决方案非常简单。除了主/ UI线程之外,无法更改任何其他线程中的UI。这就是为什么在回调方法中这样做不起作用。但是,在UI线程中创建一个Handler(例如在onCreate()方法中)将其连接到UI线程,稍后可以用于将事件发布到该线程。
mListUpdateHandler = new Handler();
然后,在完成UI调整的地方需要一个实现Runnable接口的内部类。
class UpdateListRunnable implements Runnable {
@Override
public void run() {
Log.i(LOGTAG, "UpdateListRunnable");
FriendsActivity.this.updateLists();
}
}
最后,在回调方法中,我们通过Handler将带有UpdateListRunnable类的事件发布到主线程:
@Override
public void entriesUpdated(Collection<String> entries) {
Log.i(LOGTAG, "entriesUpdated");
for (String entry : entries) {
Log.i(LOGTAG, "entry: " + entry);
}
mListUpdateHandler.post(new UpdateListRunnable());
}
多亏了upadteLists()方法在UI线程中运行,一切都像魅力一样。
答案 0 :(得分:0)
我的申请遇到了同样的问题。第一个解决方案是使用Handler。更优雅的是使用装载机 - 检查http://developer.android.com/guide/components/loaders.html! 旧版Android的兼容包使它们可用于Android 1.6 +