Ma listeCode de fragmentation
public class ItemFragment extends ListFragment {
private DatabaseHandler dbHelper;
private static final String TITLE = "Items";
private static final String LOG_TAG = "debugger";
private ItemAdapter adapter;
private List<Item> items;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.item_fragment_list, container, false);
return view;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
getActivity().setTitle(TITLE);
dbHelper = new DatabaseHandler(getActivity());
items = dbHelper.getItems();
adapter = new ItemAdapter(getActivity().getApplicationContext(), items);
this.setListAdapter(adapter);
}
@Override
public void onResume() {
super.onResume();
items.clear();
items = dbHelper.getItems(); //reload the items from database
adapter.notifyDataSetChanged();
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
if(dbHelper != null) { //item is edited
Item item = (Item) this.getListAdapter().getItem(position);
Intent intent = new Intent(getActivity(), AddItemActivity.class);
intent.putExtra(IntentConstants.ITEM, item);
startActivity(intent);
}
}
}
Ma liste
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Mais cela ne rafraîchit pas le fichier ListView
. Même après le redémarrage de l'application, les éléments mis à jour ne sont pas affichés. Mon ItemAdapter
étendBaseAdapter
public class ItemAdapter extends BaseAdapter{
private LayoutInflater inflater;
private List<Item> items;
private Context context;
public ProjectListItemAdapter(Context context, List<Item> items) {
super();
inflater = LayoutInflater.from(context);
this.context = context;
this.items = items;
}
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int position) {
return items.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ItemViewHolder holder = null;
if(convertView == null) {
holder = new ItemViewHolder();
convertView = inflater.inflate(R.layout.list_item, parent,false);
holder.itemName = (TextView) convertView.findViewById(R.id.topText);
holder.itemLocation = (TextView) convertView.findViewById(R.id.bottomText);
convertView.setTag(holder);
} else {
holder = (ItemViewHolder) convertView.getTag();
}
holder.itemName.setText("Name: " + items.get(position).getName());
holder.itemLocation.setText("Location: " + items.get(position).getLocation());
if(position % 2 == 0) {
convertView.setBackgroundColor(context.getResources().getColor(R.color.evenRowColor));
} else {
convertView.setBackgroundColor(context.getResources().getColor(R.color.oddRowColor));
}
return convertView;
}
private static class ItemViewHolder {
TextView itemName;
TextView itemLocation;
}
}
Quelqu'un peut-il aider s'il vous plaît?
adapter
référence, pourquoi le testez-vous pour null une ligne ci-dessous?Réponses:
Regardez votre
onResume
méthode dansItemFragment
:ce que vous venez de mettre à jour avant d'appeler
notifyDataSetChanged()
n'est pas le champ de l'adaptateurprivate List<Item> items;
mais le champ déclaré à l'identique du fragment. L'adaptateur stocke toujours une référence à la liste des éléments que vous avez transmis lors de la création de l'adaptateur (par exemple dans onCreate de fragment). Le moyen le plus court (en termes de nombre de modifications) mais non élégant de faire en sorte que votre code se comporte comme prévu est simplement de remplacer la ligne:avec
Une solution plus élégante:
1) supprimer des éléments
private List<Item> items;
deItemFragment
- nous devons garder la référence à eux uniquement dans l'adaptateur2) remplacez onCreate par:
3) ajouter une méthode dans ItemAdapter:
4) Changez votre onResume en:
la source
adapter.swapItems();
et l'adaptateur ferait ledbHelper.getItems()
nécessaire. Mais de toute façon merci pour la réponse :)notifyDataSetChanged()
?Vous affectez des éléments rechargés à des éléments de variable globale dans
onResume()
, mais cela ne se reflétera pas dans laItemAdapter
classe, car il a sa propre variable d'instance appelée «éléments».Pour rafraîchir
ListView
, ajoutez un refresh () dans laItemAdapter
classe qui accepte les données de liste, c'est-à-dire les élémentsmettre
onResume()
à jour avec le code suivantla source
Dans onResume () changez cette ligne
à
Le problème est que vous ne communiquez jamais à votre adaptateur la liste des nouveaux éléments. Si vous ne voulez pas transmettre une nouvelle liste à votre adaptateur (comme il semble que vous ne le faites pas), utilisez simplement
items.addAll
après votreclear()
. Cela garantira que vous modifiez la même liste à laquelle l'adaptateur fait référence.la source
adapter.clear()
ne pas forcer l'adaptateur à se rendre compte que la vue doit être actualisée, maisadapter.add()
ou leadapter.addAll()
fait. Merci pour la réponse!items.addAll()
et non adapter.addAll (). La seule chose qui laisse l'adaptateur réagir aux changements est lenotifyDataSetChanged
. La raison pour laquelle l'adaptateur voit des modifications est que laitems
liste est la même que celle utilisée par l'adaptateur.Si l'adaptateur est déjà défini, le redéfinir n'actualisera pas la liste. Au lieu de cela, vérifiez d'abord si la vue de liste a un adaptateur, puis appelez la méthode appropriée.
Je pense que ce n'est pas une très bonne idée de créer une nouvelle instance de l'adaptateur tout en définissant la vue de liste. Au lieu de cela, créez un objet.
Vous pouvez également essayer d'exécuter la liste d'actualisation sur UI Thread:
la source
ItemAdapter
est que je veux colorer les lignes et la vue de la liste affiche plusieurs éléments de données. J'ai posté le code de l'adaptateur.Si vous souhaitez mettre à jour votre liste, peu importe si vous souhaitez le faire sur
onResume()
,onCreate()
ou dans une autre fonction, la première chose que vous devez réaliser est que vous n'aurez pas besoin de créer une nouvelle instance de l'adaptateur, il suffit de remplir les tableaux avec vos données à nouveau. L'idée est quelque chose de similaire à ceci:Donc, en fonction de cette réponse, vous devez utiliser la même chose
List<Item>
dans votre fichierFragment
. Lors de votre première initialisation d'adaptateur, vous remplissez votre liste avec les éléments et définissez l'adaptateur sur votre liste. Après cela, à chaque modification de vos éléments, vous devez effacer les valeurs du principalList<Item> items
et le remplir à nouveau avec vos nouveaux éléments et appelernotifySetDataChanged();
.Voilà comment ça marche :).
la source
Une réponse d'AlexGo a fait l'affaire pour moi:
La mise à jour de la liste a fonctionné pour moi auparavant lorsque la mise à jour a été déclenchée à partir d'un événement d'interface graphique, étant ainsi dans le thread d'interface utilisateur.
Cependant, lorsque je mets à jour la liste à partir d'un autre événement / thread - c'est-à-dire un appel de l'extérieur de l'application, la mise à jour ne serait pas dans le thread d'interface utilisateur et elle a ignoré l'appel à getListView. L'appel de la mise à jour avec runOnUiThread comme ci-dessus a fait l'affaire pour moi. Merci!!
la source
Essaye ça
la source
Essayez ceci dans la
onPause()
méthode de la classe d'activité.la source
devrait faire l'affaire.
la source
Si votre liste est contenue dans l'adaptateur lui-même, l'appel de la fonction qui met à jour la liste doit également appeler
notifyDataSetChanged()
.L'exécution de cette fonction à partir du fil UI a fait l'affaire pour moi:
La
refresh()
fonction à l'intérieur de l'adaptateurEnsuite, exécutez à son tour cette fonction à partir du fil de discussion de l'interface utilisateur
la source
Essayez comme ceci:
au lieu de:
Vous devez
notifyDataSetChanged()
leListView
pas à la classe d'adaptation.la source