2012-08-11 1 views
2

Comment puis-je obtenir la vue Android actuelle lorsqu'elle affiche des données mises à jour et qu'elle doit être redessinée? J'ai travaillé à travers Notepad tutorial d'Android et terminé la leçon trois sans aucun problème — la solution est fournie, après tout — mais je suis coincé sur ma première modification non trivial.Obtenir la vue Android actuelle et la forcer à être redessinée

J'ai ajouté un nouveau bouton au menu, à côté du bouton Ajouter une note. Lorsqu'elle est pressée, cette touche ajoute une lettre au titre de chaque note du système. Cependant, les nouveaux titres n'apparaissent pas dans la liste des notes, peu importe combien de temps j'attends. Je sais que le programme de mise à jour fonctionne parce que les changements apparaissent si je rejette l'application et la ramène. Jusqu'ici, j'ai découvert que je devais utiliser une sorte de méthode d'invalidation pour que le programme se redessine avec les nouvelles valeurs. Je sais que invalidate() est utilisé à partir du thread UI et postInvalidate() est utilisé à partir de threads non-UI 1, 2, mais je ne sais même pas quel thread je suis po Aussi, ces deux méthodes doivent être appelées à partir l'objet View qui doit être dessiné, et je ne sais pas comment l'obtenir. Tout ce que j'essaie retourne null.

Ma principale classe:

public boolean onMenuItemSelected(int featureId, MenuItem item) { 
    switch(item.getItemId()) { 
     case INSERT_ID: 
      createNote(); 
      return true; 
     case NEW_BUTTON: 
      expandTitles(); 
      return true; 
     default: 
      // Intentionally empty 
    } 
    return super.onMenuItemSelected(featureId, item); 
} 

private void expandTitles() { 
    View noteListView = null; 

    // noteListView = findViewById(R.layout.notes_list); // null 

    // noteListView = 
    // getWindow().getDecorView().findViewById(android.R.id.content); 
    // From SO question 4486034 

    noteListView = findViewById(R.id.body); // Fails 

    mDbHelper.expandNoteTitles(noteListView); 
} 

Ma classe DAO:

public void expandNoteTitles(View noteListView) { 
    Cursor notes = fetchAllNotes(); 
    for(int i = 1; i <= notes.getCount(); i++) { 
     expandNoteTitle(i); 
    } 

    // NPE here when attempt to redraw is not commented out 
    noteListView.invalidate(); // Analogous to AWT's repaint(). Not working. 
    // noteListView.postInvalidate(); // Like repaint(). Not working. 
} 

public void expandNoteTitle(int i) { 
    Cursor note = fetchNote(i); 
    long rowId = 
     note.getLong(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_ROWID)); 
    String title = 
     note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)) + "W"; 
    String body = 
     note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)); 
    updateNote(rowId, title, body); 
} 

Que dois-je faire pour obtenir les titres de notes mises à jour pour afficher dès que j'appuie sur le bouton?

De toute évidence, je suis un débutant complet à Android. Je signale ceci pour vous encourager à utiliser de petits mots et à expliquer même des choses évidentes. Je sais que c'est la millionième question "Android ne pas redessiner", mais j'ai lu des douzaines de messages existants et ils ne s'appliquent pas ou n'ont pas de sens pour moi.

1: What does postInvalidate() do?
2: What is the difference between Android's invalidate() and postInvalidate() methods?

Répondre

1

Selon le tutoriel, la liste des notes existantes sont présentées dans un ListView. Il s'agit d'une vue basée sur une carte, de sorte que les éléments affichés proviennent d'un adaptateur qui étend la classe BaseAdapter. Dans ce cas, vous devez informer l'adaptateur que le contenu a été modifié en appelant sa méthode notifyDatasetChanged. Cela va signaler à ListView de mettre à jour et redessiner ses lignes.

Edit:

Désolé, je me rends compte maintenant que cet exemple utilise CursorAdapters. Ils génèrent les éléments à afficher à partir d'un objet Cursor obtenu à partir d'une requête de base de données. Maintenant, ce que notifyDatasetChanged() indique à l'adaptateur, c'est que les données qui supportent l'adaptateur ont changé, donc les Views qui montrent des choses basées sur cet adaptateur doivent redessiner leur contenu. Dans le cas d'un CursorAdapter, ces données proviennent d'un curseur. Donc, vous devez également actualisez ce curseur, rafraîchissant à partir du DB, comme ceci:

private void expandTitles() { 
     mDbHelper.expandNoteTitles(); 

     CursorAdapter adapter = (CursorAdapter)getListAdapter(); 
     adapter.getCursor().requery(); 
    } 

La méthode Requery() appelle automatiquement le notifyDatasetChanged() dans ce cas, vous n'avez pas à vous inquiéter à ce sujet , la liste va se mettre à jour.Voir aussi ce fil: https://groups.google.com/forum/?fromgroups#!topic/android-developers/_FrDcy0KC-w%5B1-25%5D.

+0

Si je vous comprends bien, la vue est basée sur 'SimpleCursorAdapter' vu dans' fillData() '. J'ai enlevé 'noteListView' et ajouté' SimpleCursorAdapter listAdapter = (SimpleCursorAdapter) getListAdapter(); listAdapter.notifyDataSetChanged(); 'après l'appel de' expandNoteTitles() ', mais n'a vu aucun changement dans le comportement de l'application. – Pops

+0

Bizarrement, cela fonctionne sur mon émulateur, mais pas sur mon téléphone, même s'ils utilisent la même version d'Android. Je suppose que c'est une question distincte. – Pops

Questions connexes