【发布时间】:2012-03-06 21:35:48
【问题描述】:
我已经为此苦苦挣扎了一段时间。在我的项目中有几个活动,包括一个 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 线程中运行,一切都像魅力一样工作。
【问题讨论】:
标签: android listview baseadapter