J'ai une base de données sur un serveur et à partir d'une tablette, je prends certaines valeurs d'une table de la base de données. Je charge correctement ces informations dans une liste mais je voudrais savoir pourquoi quand il y a un changement, rien ne se passe même si j'utilise notifyDataSetChanged();
. Je dois dire que pour charger les données de chargement, utilisez le AsyncTaskClass Donc, mon problème est que je ne sais pas si j'utilise le notifyDataSetChanged (); correctement, car s'il y a un changement, je voudrais rafraîchir l'image. Voici une partie du code de la classe:
@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();
}
});
}
}
}
L'une des principales raisons pour lesquelles notifyDataSetChanged()
ne fonctionnera pas pour vous - est,
Votre adaptateur perd la référence à votre liste.
Lorsque vous initialisez pour la première fois le Adapter
, il prend une référence de votre arrayList
et le transmet à sa superclasse. Mais si vous réinitialisez votre arrayList
existant, il perd la référence, et donc le canal de communication avec Adapter
.
Lors de la création et de l'ajout d'une nouvelle liste au Adapter
. Suivez toujours ces directives:
arrayList
tout en le déclarant globalement.arrayList
, il s'en occupera, mais ne perdra jamais la référence.adapter.clear()
et arrayList.clear()
avant d'ajouter réellement des données à la liste) mais ne définissez pas l'adaptateur ie Si les nouvelles données sont remplies dans le arrayList
que simplement adapter.notifyDataSetChanged()
Restez fidèle à la documentation.
La chose que vous devez modifier est de mettre votre
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();
}
});
dans OnCreate (). et renvoyez la liste candidatosList d'Asynctask. que de régler la minuterie pour la mise à jour de la liste candidatosList.
Il peut être utile de vérifier si vous avez un remplacement vide pour registerDataSetObserver()
. Android Studio en a ajouté un pour moi sans implémenter l'appel à super. L'ajouter comme suit était suffisant pour que ma listView fonctionne à nouveau:
@Override
public void registerDataSetObserver(DataSetObserver observer) {
super.registerDataSetObserver(observer);
}
Un adaptateur définit le comportement de la mise en page! -> setListAdapter (): Définissez l'adaptateur pour un ListView/GridView/Gallery ... mais vous devez spécifier les données!
Je vous recommande d'initialiser 'setListAdapter' dans 'onCreate' ou dans le constructeur. Après avoir défini les données dans l'adaptateur (exemple: adapter.setItem (yourData))
Et maintenant ! Vous devez appeler notifyDataSetChanged! Parce que vous avez modifié les données mais la vue n'est pas actualisée et notifydatasetchanged () recharge le contenu de la vue (ListView/GridView/Gallery ... )
Pour une bonne pratique et bien comprendre, je vous recommande d'utiliser un 'adaptateur personnalisé' en utilisant ' baseAdapter '
Lisez et faites ce tutoriel (j'ai appris avec cela): http://www.androidhive.info/2012/02/02/Android-custom-listview-with-image-and-text/
Lisez la documentation: http://developer.Android.com/reference/Android/widget/BaseAdapter.html
La fonction de mise à jour doit être appelée à partir du thread d'interface utilisateur. Ma réponse est en fait similaire à celle de @ user1621629 answer avec cette différence que j'utilise rxJava, alors voici le code de travail qui résout ce problème pour moi:
this.subscriber = myAdapter.getSubscriber(); // keep for unsubscribe in destroy
dataSource.subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).subscribe(this.subscriber);
J'ai donc défini toutes les exécutions afin d'obtenir des données pour la liste sur le thread de calcul, mais montrant le résultat dans le thread d'interface utilisateur.
Voici comment je crée un abonné pour cela:
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();
}
});
}
......
Comme Hissain décrit ci-dessus ,
vous devez conserver une référence à la liste
Voici comment je l'ai fait fonctionner:
Laissez la liste envoyée à l'adaptateur être définie en tant que membre d'instance dans l'activité
Dans la logique qui effectue une modification des données, assurez-vous qu'elle met à jour la même instance de liste que l'activité transmise à l'adaptateur
Appelant ensuite .notifyDataSetChanged (); travaillé
N'oubliez pas que la position listView commence à 1, vous devrez donc faire (listViewPosition - 1) pour votre Java.util.List
Je n'ai pas beaucoup de réputation pour commenter la réponse de M. Hissain. C'est correct mais je veux mentionner une chose de plus que la référence à la liste ne devrait pas changer. Si la source de données sous-jacente change, ne modifiez pas la référence à la nouvelle liste. Les actions doivent uniquement être effectuées sur le même objet de liste. Pour faire de même, effacez la liste à l'aide de clear (), puis ajoutez des données à la même liste à l'aide de add () ou addALL (), puis appelez notifyDataSetChanged (). par exemple. Lors de la première initialisation de la liste
list = dataSource.getList();
alors on peut ajouter et supprimer le contenu de la liste et appeler notifyDataSetChanged () ça marche bien mais si dans le code, on essaie de changer la référence à l'autre objet. Comme
list = dataSource.getList();
où getList () renvoie la nouvelle liste à chaque fois, donc la référence change à un autre objet de liste et l'appel à notifyDataSetChnaged n'a pas d'impact sur la liste.Mais si getList () renvoie le même objet de liste, cela fonctionne très bien.