5

私はしばらくこれに苦労してきました。私のプロジェクトには、ListView と BaseAdapter を拡張するカスタム アダプターを含むアクティビティがいくつかあります。また、通常はデータが変更されたことを通知するいくつかのインターフェースも実装しています。

ただし、クラスに実装されているリスナー/インターフェイス メソッドから notifyDataSetChanged() を呼び出すと、ListView は更新されず、アダプター メソッドは呼び出されません (getCount()、getView())。

これは、notifyDataSetChanged() が呼び出された場所、つまりどのスレッドと関係があるかはわかっていますが、よく理解できず、この動作の簡単な説明を見つけることができませんでした。

この問題の回避策として、メソッドを定期的に呼び出すハンドラーを使用し、そのメソッドでブール値の「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 スレッド (onCreate() メソッドなど) でハンドラを作成すると、ハンドラが UI スレッドに接続され、後でこのスレッドにイベントを投稿するために使用できます。

mListUpdateHandler = new Handler();

次に、Runnable インターフェースを実装する内部クラスが、UI の微調整が行われる場所で必要になります。

class UpdateListRunnable implements Runnable {
        @Override
        public void run() {
            Log.i(LOGTAG, "UpdateListRunnable");
            FriendsActivity.this.updateLists();            
        }
    }

最後に、コールバック メソッドで、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 に答える