我已经为此苦苦挣扎了一段时间。在我的项目中有几个活动,包括一个 ListView 和一个扩展 BaseAdapter 的自定义适配器。他们还实现了一些接口,这些接口通常会通知它数据已更改。
但是,当我从类中实现的侦听器/接口方法调用 notifyDataSetChanged() 时,ListView 没有更新,并且没有调用任何适配器方法(getCount()、getView())。
我知道这与从哪个线程调用 notifyDataSetChanged() 的事实有关,我的意思是哪个线程,但我不太明白,也找不到对这种行为的直接解释。
作为此问题的解决方法,我使用了一个定期调用方法的处理程序,在该方法中,我查看布尔值“needsToBeUpdated”是否为真,然后调用 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 线程中创建一个处理程序(例如在 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 线程中运行,一切都像一个魅力。