5

我已经为此苦苦挣扎了一段时间。在我的项目中有几个活动,包括一个 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 线程中运行,一切都像一个魅力。

4

1 回答 1

0

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

于 2012-07-11T13:40:33.220 回答