从侦听器回调方法调用Android的BaseAdapter notifyDataSetChanged()

时间:2012-03-06 21:35:48

标签: android listview baseadapter

我一直在努力解决这个问题。在我的项目中,有几个活动包括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线程中运行,一切都像魅力一样。

1 个答案:

答案 0 :(得分:0)

我的申请遇到了同样的问题。第一个解决方案是使用Handler。更优雅的是使用装载机 - 检查http://developer.android.com/guide/components/loaders.html! 旧版Android的兼容包使它们可用于Android 1.6 +