私はしばらくこれに苦労してきました。私のプロジェクトには、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 スレッドで実行され、すべてがうまく機能します。