Salut
J'ai créé une ListView avec un custom adapter pour pouvoir afficher des éléments avec un layout personnalisé, j'ai suivi plusieurs tuto notamment celui d'Andr0 ainsi que plusieurs réponses sur stackoverflow. Là dessus pas de problème j'arrive à afficher tous mes éléments de ma base. Mon problème survient lorsque je veux ajouter un élément à ma listview déjà remplie, si je modifie l'ArrayList (laquelle contient toutes mes items de ma ListView) puis que j'appelle java adapter.notifyDataChanged()
ma liste est bien mise à jour mais tous les items sont dupliqués.
Voici mon code :
MyListFragment.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | public class MyListFragment extends ListFragment { private static final String TAG = "ListFragment"; private List<List<String>> content = new ArrayList<List<String>>(); private Context mContext; private View mView; private ListViewAdapter adapter; // RECEIVER private BroadcastReceiver mMessageReceiver; private static String REMOVE_ITEM = "remove_item"; private static String ADD_ITEM = "add_item"; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.list_routes_fragment, container, false); mContext = getActivity(); // Broadcast receiver filter mContext.registerReceiver(mMessageReceiver, new IntentFilter(REMOVE_ITEM)); mContext.registerReceiver(mMessageReceiver, new IntentFilter(ADD_ITEM)); mMessageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action != null) { if (action.equals(REMOVE_ITEM)) { int position = Integer.valueOf(intent.getStringExtra("position")); content.remove(position); adapter.notifyDataSetChanged(); } else if(action.equals(ADD_ITEM)) { List<String> item = intent.getStringArrayListExtra("item"); content.add(item); adapter.notifyDataChanged(); } } } }; return mView; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); new databaseTask().execute(""); } @Override public void onResume() { // Broadcast receiver filter mContext.registerReceiver(mMessageReceiver, new IntentFilter(REMOVE_ITEM)); mContext.registerReceiver(mMessageReceiver, new IntentFilter(ADD_ITEM)); super.onResume(); } @Override public void onPause() { mContext.unregisterReceiver(mMessageReceiver); super.onPause(); } @Override public void onDestroy() { super.onDestroy(); } public class databaseTask extends AsyncTask<String, Integer, String> { @Override protected String doInBackground(String... params) { SQLiteHelper db = new SQLiteHelper(mContext); // Get all routes List<Route> routes = db.getRoutes(); if (routes != null && routes.size() > 0) { for (Route route : routes) { List<String> listRoute = new ArrayList<String>(); // Add Date listRoute.add(route.getDateTime()); // Add Time String time = db.getRouteStatName(routeId, getResources().getString(R.string.statTime)); listRoute.add(time); // Add Route Id listRoute.add(route.getRouteId() + ""); // Add list to content content.add(listRoute); } } return null; } @Override protected void onPostExecute(String result) { // Set adapter adapter = new ListViewAdapter(getActivity(), content); setListAdapter(adapter); } } } |
ListViewAdapter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | public class ListViewAdapter extends ArrayAdapter<List<List<String>>> { private static final String TAG = "ListViewAdapter"; private Context mContext; private List<List<String>> adapter; // RECEIVER private BroadcastReceiver mMessageReceiver; private static String REMOVE_ITEM = "remove_item"; public ListViewAdapter(Context context, List<List<String>> content) { super(context, R.layout.custom_layout_route); mContext = context; adapter = content; } @Override public int getCount() { return adapter.size(); } @Override public long getItemId(int position) { return adapter.indexOf(getItem(position)); } @Override public View getView(final int position, View convertView, ViewGroup parent) { View rowView = convertView; ViewHolder view; if(rowView == null) { // Get a new instance of the row layout view LayoutInflater inflater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); rowView = inflater.inflate(R.layout.custom_layout_route,parent, false); // Hold the view objects in an object, that way the don't need to be "re- finded" view = new ViewHolder(); view.textviewDate = (TextView) rowView.findViewById(R.id.textviewDate); view.textviewTime = (TextView) rowView.findViewById(R.id.textviewTime); view.btDelete = (ImageButton) rowView.findViewById(R.id.btDelete); rowView.setTag(view); } else { view = (ViewHolder) rowView.getTag(); } List<String> route = new ArrayList<String>(); route = adapter.get(position); String date = route.get(0).toString(); String time = route.get(1).toString(); final String routeId = route.get(2).toString(); view.textviewDate.setText(date); view.textviewTime.setText(time); // Set click listener on remove button view.btDelete.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new AlertDialog.Builder(mContext) .setTitle(mContext.getString(R.string.delete_route_title)) .setMessage(mContext.getString(R.string.delete_route_message)) .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { SQLiteHelper db = new SQLiteHelper(mContext); db.removeRoute(Integer.parseInt(routeId)); // Send Broadcast to remove item from listview Intent i = new Intent(REMOVE_ITEM); i.putExtra("position", position + ""); mContext.sendBroadcast(i.setAction(REMOVE_ITEM)); // Tell user the route is deleted Toast.makeText(mContext, getRessource().getString().RouteDelete, Toast.LENGTH_SHORT).show(); } }) .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // do nothing } }) .show(); } }); return rowView; } protected static class ViewHolder{ protected TextView textviewDate; protected TextView textviewTime; protected ImageButton btDelete; } } |
Le plus frustrant c'est que je comprends pourquoi il me duplique ma liste, c'est lorsque je fais
1 2 3 4 5 | List<String> item = intent.getStringArrayListExtra("item"); content.add(item); adapter.notifyDataChanged(); |
Je lui dis "Hé ! Le contenu de la ListView a changé tu pourrais me la rafraîchir steuplé ? " Seulement j'aurais crû que qu'il aurait été assez intelligent pour rajouter uniquement le nouvel élément et pas toute la liste. J'ai testé beaucoup (toutes ?) de réponses sur Stack et autre blog mais je pense qu'il y a un truc que j'ai pas dû bien comprendre sur les adapter.
Merci d'avance à ceux qui pourront m'aider