【问题标题】:Calling Android's BaseAdapter notifyDataSetChanged() from a listener callback method从侦听器回调方法调用 Android 的 BaseAdapter notifyDataSetChanged()
【发布时间】: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


    【解决方案1】:

    我的申请遇到了同样的问题。第一个解决方案是使用处理程序。更优雅的是使用加载器 - 检查http://developer.android.com/guide/components/loaders.html! 旧 android 版本的兼容性包使其可用于 Android 1.6+

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-08
      • 2020-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多