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:
- Configure
onItemClickListener
separado para cada vista en el adaptador - Envíalo a donde quieras manejarlo
- 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 :
- invalidar () O
- 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);
}