サーバーにデータベースがあり、タブレットからデータベースの1つのテーブルからいくつかの値を取得します。この情報をリストに正しくロードしますが、変更があるときにnotifyDataSetChanged();
を使用しても何も起こらない理由を知りたいです。読み込みデータを読み込むには、AsyncTaskClassを使用する必要があると言わなければなりません。したがって、私の問題は、notifyDataSetChanged()を使用するかどうかわからないことです。メソッドが正しく変更されている場合は、画像を更新したいので。クラスのコードの一部を次に示します。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.all_candidatos);
candidatosList = new ArrayList<HashMap<String, String>>();
new CargarCandidatos().execute();
}
// public void timer(){
// new CountDownTimer(tiempo, 100) {
//
// public void onTick(long millisUntilFinished) {
//
// }
//
// public void onFinish() {
// // new CargarCandidatos().execute();
//
// }
// }.start();}
/**
* Background Async Task to Load all product by making HTTP Request
* */
class CargarCandidatos extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(Monitorizacion.this);
pDialog.setMessage("Loading ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* getting All products from url
* */
protected String doInBackground(String... args) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
JSONObject json = jParser.makeHttpRequest(url_candidatos, "GET", params);
Log.d("Candidatos: ", json.toString());
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
candidatos = json.getJSONArray(TAG_CANDIDATOS);
for (int i = 0; i < candidatos.length(); i++) {
JSONObject c = candidatos.getJSONObject(i);
// Storing each json item in variable
String nserie = c.getString(TAG_NSERIE);
String dni = c.getString(TAG_DNI);
String nombre = c.getString(TAG_NOMBRE);
String test = c.getString(TAG_TEST);
String pregunta = c.getString(TAG_PREGUNTA);
String bateria = c.getString(TAG_BATERIA);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_NSERIE, nserie);
map.put(TAG_DNI, dni);
map.put(TAG_NOMBRE, nombre);
map.put(TAG_TEST, test);
map.put(TAG_PREGUNTA, pregunta);
map.put(TAG_BATERIA, bateria);
// adding HashList to ArrayList
candidatosList.add(map);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url) {
pDialog.dismiss();
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
adapter = new SimpleAdapter(
Monitorizacion.this, candidatosList,
R.layout.list_item, new String[] { TAG_NSERIE,
TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA},
new int[] { R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria});
setListAdapter(adapter);
adapter.notifyDataSetChanged();
// timer();
}
});
}
}
}
notifyDataSetChanged()
が機能しない主な理由の1つは、
アダプタはリストへの参照を失います。
Adapter
を最初に初期化すると、arrayList
の参照が取得され、スーパークラスに渡されます。ただし、既存のarrayList
を再初期化すると、参照が失われるため、Adapter
との通信チャネルが失われます。
新しいリストを作成してAdapter
に追加するとき。常に次のガイドラインに従ってください。
arrayList
を初期化します。arrayList
のデータをどこで変更してもそれが処理されることを保証しますが、参照を失うことはありません。adapter.clear()
およびarrayList.clear()
を呼び出すことができます)が、アダプターを設定しないでください。新しいデータがadapter.notifyDataSetChanged()
よりもarrayList
に入力されている場合ドキュメントを忠実に守ってください。
編集する必要があるのは
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
adapter = new SimpleAdapter(
Monitorizacion.this, candidatosList,
R.layout.list_item, new String[] { TAG_NSERIE,
TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA},
new int[] { R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria});
setListAdapter(adapter);
adapter.notifyDataSetChanged();
// timer();
}
});
onCreate()に。 AsynctaskからリストcandidatosListを返します。 candidatosListリストを更新するためのタイマーを設定するよりも。
registerDataSetObserver()
の空のオーバーライドがあるかどうかを確認する価値があるかもしれません。 Androidスタジオはsuperへの呼び出しを実装せずに追加しました。listViewを再び機能させるには、次のように追加するだけで十分です。
@Override
public void registerDataSetObserver(DataSetObserver observer) {
super.registerDataSetObserver(observer);
}
アダプタは、レイアウトの構成を定義します! -> setListAdapter():ListView/GridView/Galleryのアダプターを定義します...しかし、データを指定する必要があります!
'onCreate'またはコンストラクターで 'setListAdapter'を初期化することをお勧めします。データをアダプターに設定した後(例:adapter.setItem(yourData))
そしていま ! notifyDataSetChangedを呼び出す必要があります! データを変更しましたが、ビューは更新されず、notifydatasetchanged()はビューのコンテンツをリロードするため(ListView/GridView/Gallery ... )
適切なプラクティスと適切な理解のために、「baseAdapter」を使用して「カスタムアダプタ」を使用することをお勧めします
このチュートリアルを読んで実行します(これで学習しました): http://www.androidhive.info/2012/02/Android-custom-listview-with-image-and-text/
ドキュメントを読む: http://developer.Android.com/reference/Android/widget/BaseAdapter.html
更新関数はUIスレッドから呼び出す必要があります。私の答えは実際には@ user1621629の answer に似ていますが、rxJavaを使用しているという違いがあるため、この問題を解決する作業コードを次に示します。
this.subscriber = myAdapter.getSubscriber(); // keep for unsubscribe in destroy
dataSource.subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).subscribe(this.subscriber);
したがって、リストのデータを計算スレッドに取得するためにすべての実行を設定しますが、UIスレッドで結果を表示します。
これは私がこれのためにサブスクライバーを作成する方法です:
public class MyListAdapter extends RecyclerView.Adapter<LocationListAdapter.ViewHolder> {
private List<ListItem> mDataset = new ArrayList<>();
public Subscriber<ListItem[]> getSubscriber() {
return Subscribers.create(new Action1<ListItem[]>() {
@Override
public void call(ListItem[] listItems) {
mDataset.clear();
mDataset.addAll(Arrays.asList(listItems));
notifyDataSetChanged();
}
});
}
......
Hissainは上記で説明 のように、
リストへの参照を維持する必要があります
これがどのように機能するようになったかです:
アダプターに送信されるリストを、アクティビティのインスタンスメンバーとして設定します。
データの変更を実行するロジックで、アクティビティがアダプターに渡したのと同じリストインスタンスを更新することを確認します
次に、.notifyDataSetChanged();を呼び出します。働いた
ListViewの位置は1から始まるため、Java.util.Listに対して(listViewPosition-1)を実行する必要があることに注意してください。
Hissain氏の回答についてコメントする評判はあまりありませんが、それは正しいですが、リストへの参照が変更されるべきではないことをもう1つ言及したいと思います。基になるデータソースが変更されている場合、新しいリストへの参照を変更しないでください。アクションは、同じリストオブジェクトに対してのみ実行する必要があります。同じことを行うには、clear()を使用してリストをクリアし、add()またはaddALL()を使用して同じリストにデータを追加し、notifyDataSetChanged()を呼び出します。例えば。リストの最初の初期化時
list = dataSource.getList();
次に、リストからコンテンツを追加および削除し、notifyDataSetChanged()を呼び出して正常に動作しますが、コード内で他のオブジェクトへの参照を変更しようとします。お気に入り
list = dataSource.getList();
getList()は毎回新しいリストを返すため、参照は他のリストオブジェクトに変更され、notifyDataSetChnagedの呼び出しはリストに影響を与えませんが、getList()が同じリストオブジェクトを返す場合、正常に動作します。