tutorial recyclerview example custom arrayadapter activity android listview android-listview

recyclerview - listview android example



Solo en algunos teléfonos, ListView no se actualiza después de notifyDataSetChanged() (8)

Es raro porque ocurre solo en algunos teléfonos, esa resolución es FHD.

Cuando se muestra la interfaz de usuario, todo parece estar bien. Cuando hago clic en los elementos y llamo a NotifyDataSetChanged (), el elemento no se actualiza. Necesito hacer clic en el ListView de nuevo en cualquier lugar, el elemento actualizará el diseño al aspecto correcto.

Si la vista de lista cambia de tamaño (por ejemplo, la función de búsqueda rediseñará todo el diseño), todo estará bien.

Aquí está el código de ListView:

public final class MyListView extends ListView implements AdapterView.OnItemClickListener { ArrayList<SELECT_ITEM> selectList; ArrayList<ID_ITEM> idList; ShowItemAdapter showAdapter; public MyListView(Context context) { selectList = new ArrayList<SELECT_ITEM>(); idList = new ArrayList<ID_ITEM>(); readIdList(mIdList); showAdapter = new ShowItemAdapter(context, idList, selectList); setAdapter(showAdapter); ... } @Override protected void onFinishInflate() { setOnItemClickListener(this); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long ID) { boolean itemIsSelected = true; int size = selectList.size(); // remove if click item in selectList for(int i=0 ; i<size ; i++) { int selectID = selectList.get(i).id; if (idList.get(position).id == selectID) { itemIsSelected = false; selectList.remove(i); showAdapter.notifyDataSetChanged(); break; } } if (itemIsSelected) { SELECT_ITEM item = new SELECT_ITEM(); item.id = idList.get(position); selectList.add(item); // Here showAdapter.notifyDataSetChanged(); } ... } .... }

Y aquí está el código del adaptador,

public final class ShowItemAdapter extends BaseAdapter{ public ArrayList<ID_ITEM> mIdList; public ArrayList<SELECT_ITEM> mSelectList; public ShowItemAdapter(Context context, ArrayList<ID_ITEM> idList, ArrayList<SELECT_ITEM> selectList) { mIdList = idList; mSelectList = selectList; } @Override public int getCount() { int ret = mIdList.size(); return ret; } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ... for(int i=0 ; i<size ; i++) { // is selected if (mIdList.get(position).id == selectList.get(i).id) { mIsSelected = true; break; } } if (mIsSelected) { textView.setBackgroundColor(Color.red); } else { textView.setBackgroundColor(Color.white); } } }

¿Alguien me da una mano?

Encontré que esos teléfonos funcionan correctamente causará el mismo problema al depurar la pausa en getView (). Creo que ... es como "Las vistas se han actualizado para que no actualicen las vistas". Pero las vistas que se actualizan durante la depuración hacen que el ui no se actualice en realidad, entonces funciona de manera incorrecta.

Supongo que se trata de actualizar vistas.


A continuación podría ayudar. Tuve un problema similar en 4.4.2 y esto ayudó:

//clear the adapter showAdapter.clear(); //add all the data in your list to adapter again showAdapter.addAll(selectList);

No necesita llamar a notificationDataSetChanged, ya que lo hará en addAll. Espero que ayude.


Debe actualizar su ListView de forma síncrona.

public final class ShowItemAdapter extends BaseAdapter{ public ArrayList<ID_ITEM> mIdList; public ArrayList<SELECT_ITEM> mSelectList; public ShowItemAdapter(Context context, ArrayList<ID_ITEM> idList, ArrayList<SELECT_ITEM> selectList) { mIdList = idList; mSelectList = selectList; } public synchronized void refreshData(ArrayList<SELECT_ITEM> items) { this.mSelectList = items; notifyDataSetChanged(); }

Luego llame al método refreshData () cada vez que realice cambios en su lista

selectList.remove(i); refreshData(selectList);

o

selectList.add(i); refreshData(selectList);

Esto definitivamente actualizará la vista de la lista de usuarios con la Lista de elementos actualizada


En lugar de usar showAdapter.notifyDataSetChanged(); solo actualice su fuente de datos, me refiero a seleccionar Lista y reinicializar su adaptador y adjuntarlo a ListView.

reemplazar este

selectList.remove(i); showAdapter.notifyDataSetChanged();

y

selectList.add(item); showAdapter.notifyDataSetChanged();

con esto respectivamente

selectList.remove(i); // or selectList.add(item); showAdapter = new ShowItemAdapter(context, idList, selectList); setAdapter(showAdapter);


Encontré una solución aunque todavía funciona con algunos problemas.
Llamo a continuación en Activity.onCreate (), y solo en onInit () MyListView se iniciará:

postDelayed(new Runnable() { public void run() { onInit(icicle); // initial ui } }, 100);

Hace que la vista se muestre más lenta pero funciona bien.
Si se demora alrededor de 100 milisegundos, puede hacer que esos buenos teléfonos funcionen mal. El retraso de unos 350 milisegundos hace que ambos teléfonos funcionen bien. ¿Hay mejores respuestas?


Es el error en Android 4.0.3, notifyDataSetChanged no funciona desde onItemClickListener .

Entonces la solución sería algo como esto:

  1. Configure onItemClickListener separado para cada vista en el adaptador
  2. Envíalo a donde quieras manejarlo
  3. Haz lo que quieras y llama a notifyDataSetChanged desde allí

Normalmente actualizo los datos en mi adaptador, y no tengo este tipo de problema, creo que es más sólido. Dado que está actualizando los datos (lista de selección) en la vista de lista, la actualización / actualización es un poco indirecta, creo. Yo sugeriría al principio intentarlo.

Muestras de código después del código de abajo:

selectList.remove(i); showAdapter.notifyDataSetChanged();

AGREGAR :

  1. invalidar () O
  2. invalidateViews ()

Nota: me doy cuenta de su solución de llamar a onInit () que no tengo idea de lo que es. Parece que hay un problema de tiempo involucrado, lo que significa que no debería tener que ejecutar el código en un subproceso nuevo / separado.


Veo un posible conflicto de código y un problema de tiempo entre getView () del adaptador y el onItemClick ().

Permíteme explicarte. En getView (), hay código

if (mIdList.get(position).id == selectList.get(i).id)

Nota: Esto verifica el valor de selectList , que ni siquiera se declara en esta clase de adaptador. Supongo que quiso decir mSelectList . Pero sigamos adelante ...

En onItemClick (), hay código

if (idList.get(position).id == selectID) { ... selectList.remove(i); ...

Nota: este código elimina un elemento de selectList , mientras que en getView (), está comprobando el mismo objeto. No podemos saber qué código se ejecutará primero. Pero tengo una idea ... getView () es un método de devolución de llamada virtual en el que el BaseAdapter puede activar el método cuando requiere una fila o elemento para mostrar. Por lo tanto, cuando elimina un elemento de una vista de lista, es posible que el adaptador no solicite una actualización, independientemente de lo que haga en el código. Y el adaptador ShowItemAdapter es responsable de la actualización de todas las filas / vistas.

Sugerencia : coloque el mismo código (para eliminar / agregar un elemento) en getView () para evitar este tipo de conflictos de código.

Avísanos y buena suerte con esta extraña anomalía.
Tommy Kwee


onFinishInflate llamar a los super métodos en las funciones de constructor y onFinishInflate de la clase MyListView . Eso podría haber causado el problema.

public MyListView(Context context) { super(context); selectList = new ArrayList<SELECT_ITEM>(); .. .. }

y

@Override protected void onFinishInflate() { super.onFinishInflate(); setOnItemClickListener(this); }