update studio refrescar llenar editar dinamico con como botones actualizar android android-listview refresh

llenar - refrescar listview android studio



¿Cómo actualizar la vista de lista de Android? (25)

Ignore todas las respuestas invalidate() , invalidateViews() , requestLayout() , ... a esta pregunta.

Lo correcto (y, afortunadamente, también marcado como respuesta correcta) es llamar a notifyDataSetChanged() en su Adaptador .

Solución de problemas

Si llamar a notifyDataSetChanged() no funciona, tampoco servirán todos los métodos de diseño. Créeme, el ListView se actualizó correctamente. Si no encuentra la diferencia, debe verificar de dónde provienen los datos de su adaptador.

Si esta es solo una colección que está guardando en la memoria, realmente eliminó o agregó los elementos a la colección antes de llamar a notifyDataSetChanged() .

Si está trabajando con una base de datos o servicio de back-end, deberá llamar al método para recuperar la información nuevamente (o manipular los datos en la memoria) antes de llamar a notifyDataSetChanged() .

El problema es que notifyDataSetChanged solo funciona si el conjunto de datos ha cambiado. Así que ese es el lugar para buscar si no encuentra cambios. Depurar si es necesario.

ArrayAdapter vs BaseAdapter

Encontré que trabajar con un adaptador que te permite administrar la colección, como un BaseAdapter funciona mejor. Algunos adaptadores como ArrayAdapter ya administran su propia colección, lo que dificulta el acceso a la colección adecuada para las actualizaciones. En realidad, es solo una innecesaria capa de dificultad en la mayoría de los casos.

Hilo de la interfaz de usuario

Es cierto que esto debe ser llamado desde el hilo de la interfaz de usuario. Otras respuestas tienen ejemplos sobre cómo lograr esto. Sin embargo, esto solo es necesario si está trabajando en esta información desde fuera del hilo de la IU. Eso es de un servicio o un hilo no UI. En casos simples, actualizará sus datos con un clic de botón u otra actividad / fragmento. Así que todavía dentro del hilo de la interfaz de usuario. No es necesario que siempre pongas ese runOnUiTrhead en.

Ejemplo de proyecto rápido

Se puede encontrar en https://github.com/hanscappelle/so-2250770.git . Solo clona y abre el proyecto en Android Studio (gradle). Este proyecto tiene una actividad principal que construye un ListView con todos los datos aleatorios. Esta lista se puede actualizar usando el menú de acción.

La implementación del adaptador que creé para este ejemplo ModelObject expone la recopilación de datos

public class MyListAdapter extends BaseAdapter { /** * this is our own collection of data, can be anything we * want it to be as long as we get the abstract methods * implemented using this data and work on this data * (see getter) you should be fine */ private List<ModelObject> mData; /** * our ctor for this adapter, we''ll accept all the things * we need here * * @param mData */ public MyListAdapter(final Context context, final List<ModelObject> mData) { this.mData = mData; this.mContext = context; } public List<ModelObject> getData() { return mData; } // implement all abstract methods here }

Código del MainActivity

public class MainActivity extends Activity { private MyListAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView list = (ListView) findViewById(R.id.list); // create some dummy data here List<ModelObject> objects = getRandomData(); // and put it into an adapter for the list mAdapter = new MyListAdapter(this, objects); list.setAdapter(mAdapter); // mAdapter is available in the helper methods below and the // data will be updated based on action menu interactions // you could also keep the reference to the android ListView // object instead and use the {@link ListView#getAdapter()} // method instead. However you would have to cast that adapter // to your own instance every time } /** * helper to show what happens when all data is new */ private void reloadAllData(){ // get new modified random data List<ModelObject> objects = getRandomData(); // update data in our adapter mAdapter.getData().clear(); mAdapter.getData().addAll(objects); // fire the event mAdapter.notifyDataSetChanged(); } /** * helper to show how only changing properties of data * elements also works */ private void scrambleChecked(){ Random random = new Random(); // update data in our adapter, iterate all objects and // resetting the checked option for( ModelObject mo : mAdapter.getData()) { mo.setChecked(random.nextBoolean()); } // fire the event mAdapter.notifyDataSetChanged(); } }

Más información

Otra buena publicación sobre el poder de listViews se encuentra aquí: http://www.vogella.com/articles/AndroidListView/article.html

¿Cómo actualizar un ListView Android después de agregar / eliminar datos dinámicos?


Creo que depende de lo que quieres decir con refrescar. ¿Quiere decir que la pantalla GUI debe actualizarse o que las vistas secundarias deben actualizarse de manera que pueda llamar a getChildAt (int) programáticamente y obtener la vista correspondiente a lo que se encuentra en el Adaptador?

Si desea que se actualice la pantalla GUI, llame a notifyDataSetChanged () en el adaptador. La GUI se actualizará la próxima vez que se vuelva a dibujar.

Si desea poder llamar a getChildAt (int) y obtener una vista que refleje lo que hay en el adaptador, llame a layoutChildren (). Esto hará que la vista secundaria se reconstruya a partir de los datos del adaptador.


Debe usar un solo objeto de esa lista para los datos que está inflando en ListView . Si la referencia es el cambio, notifyDataSetChanged() funciona. Siempre que esté eliminando elementos de la vista de lista, también elimínelos de la lista que está usando, ya sea una ArrayList <> o algo más, luego llame a notifyDataSetChanged() en el objeto de su adaptador clase.

Así que aquí vea cómo lo manejé en mi adaptador, vea abajo

public class CountryCodeListAdapter extends BaseAdapter implements OnItemClickListener{ private Context context; private ArrayList<CountryDataObject> dObj; private ViewHolder holder; private Typeface itemFont; private int selectedPosition=-1; private ArrayList<CountryDataObject> completeList; public CountryCodeListAdapter(Context context, ArrayList<CountryDataObject> dObj) { this.context = context; this.dObj=dObj; completeList=new ArrayList<CountryDataObject>(); completeList.addAll(dObj); itemFont=Typeface.createFromAsset(context.getAssets(), "CaviarDreams.ttf"); } @Override public int getCount() { return dObj.size(); } @Override public Object getItem(int position) { return dObj.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View view, ViewGroup parent) { if(view==null){ holder = new ViewHolder(); LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.states_inflator_layout, null); holder.textView = ((TextView)view.findViewById(R.id.stateNameInflator)); holder.checkImg=(ImageView)view.findViewById(R.id.checkBoxState); view.setTag(holder); }else{ holder = (ViewHolder) view.getTag(); } holder.textView.setText(dObj.get(position).getCountryName()); holder.textView.setTypeface(itemFont); if(position==selectedPosition) { holder.checkImg.setImageResource(R.drawable.check); } else { holder.checkImg.setImageResource(R.drawable.uncheck); } return view; } private class ViewHolder{ private TextView textView; private ImageView checkImg; } public void getFilter(String name) { dObj.clear(); if(!name.equals("")){ for (CountryDataObject item : completeList) { if(item.getCountryName().toLowerCase().startsWith(name.toLowerCase(),0)){ dObj.add(item); } } } else { dObj.addAll(completeList); } selectedPosition=-1; notifyDataSetChanged(); notifyDataSetInvalidated(); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Registration reg=(Registration)context; selectedPosition=position; reg.setSelectedCountryCode("+"+dObj.get(position).getCountryCode()); notifyDataSetChanged(); } }


Después de eliminar los datos de la vista de lista, debe llamar a refreshDrawableState() . Aquí está el ejemplo:

final DatabaseHelper db = new DatabaseHelper (ActivityName.this); db.open(); db.deleteContact(arg3); mListView.refreshDrawableState(); db.close();

y el método deleteContact en la clase DatabaseHelper será algo así como

public boolean deleteContact(long rowId) { return db.delete(TABLE_NAME, BaseColumns._ID + "=" + rowId, null) > 0; }


Era igual cuando, en un fragmento, quería rellenar un ListView (en un solo TextView) con la dirección mac de los dispositivos BLE escaneados durante algún tiempo.

Lo que hice fue esto:

public class Fragment01 extends android.support.v4.app.Fragment implements ... { private ListView listView; private ArrayAdapter<String> arrayAdapter_string; ... @Override public void onActivityCreated(Bundle savedInstanceState) { ... this.listView= (ListView) super.getActivity().findViewById(R.id.fragment01_listView); ... this.arrayAdapter_string= new ArrayAdapter<String>(super.getActivity(), R.layout.dispositivo_ble_item, R.id.fragment01_item_textView_titulo); this.listView.setAdapter(this.arrayAdapter_string); } @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { ... super.getActivity().runOnUiThread(new RefreshListView(device)); } private class RefreshListView implements Runnable { private BluetoothDevice bluetoothDevice; public RefreshListView(BluetoothDevice bluetoothDevice) { this.bluetoothDevice= bluetoothDevice; } @Override public void run() { Fragment01.this.arrayAdapter_string.add(new String(bluetoothDevice.toString())); Fragment01.this.arrayAdapter_string.notifyDataSetChanged(); } }

Luego, el ListView comenzó a poblarse dinámicamente con la dirección mac de los dispositivos encontrados.


Las soluciones propuestas por las personas en este post funcionan o no, principalmente dependiendo de la versión de Android de su dispositivo. Por ejemplo, para usar el método AddAll tienes que poner android: minSdkVersion = "10" en tu dispositivo Android.

Para resolver estas preguntas para todos los dispositivos, creé mi propio método en mi adaptador y lo uso dentro del método de agregar y eliminar que hereda de ArrayAdapter que actualiza sus datos sin problemas.

Mi Código: Al usar mi propia clase de datos RaceResult, usas tu propio modelo de datos.

ResultGpRowAdapter.java

public class ResultGpRowAdapter extends ArrayAdapter<RaceResult> { Context context; int resource; List<RaceResult> data=null; public ResultGpRowAdapter(Context context, int resource, List<RaceResult> objects) { super(context, resource, objects); this.context = context; this.resource = resource; this.data = objects; } @Override public View getView(int position, View convertView, ViewGroup parent) { ........ } //my own method to populate data public void myAddAll(List<RaceResult> items) { for (RaceResult item:items){ super.add(item); } }

ResultadosGp.java

public class ResultsGp extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { ........... ........... ListView list = (ListView)findViewById(R.id.resultsGpList); ResultGpRowAdapter adapter = new ResultGpRowAdapter(this, R.layout.activity_result_gp_row, new ArrayList<RaceResult>()); //Empty data list.setAdapter(adapter); .... .... .... //LOAD a ArrayList<RaceResult> with data ArrayList<RaceResult> data = new ArrayList<RaceResult>(); data.add(new RaceResult(....)); data.add(new RaceResult(....)); ....... adapter.myAddAll(data); //Your list will be udpdated!!!


Llama a runnable cuando quieras:

runOnUiThread(run);

OnCreate() , configuras tu hilo ejecutable:

run = new Runnable() { public void run() { //reload content arraylist.clear(); arraylist.addAll(db.readAll()); adapter.notifyDataSetChanged(); listview.invalidateViews(); listview.refreshDrawableState(); } };



Lo más fácil es simplemente hacer un nuevo Adaper y soltar el anterior:

myListView.setAdapter(new MyListAdapter(...));


No pude hacer que notifyDataSetChanged () para trabajar en la actualización de mi SimpleAdapter, así que en lugar de eso intenté eliminar todas las vistas que se adjuntaron al diseño principal usando removeAllViews (), luego agregue el ListView, y funcionó, permitiéndome actualizar el IU:

LinearLayout results = (LinearLayout)findViewById(R.id.results); ListView lv = new ListView(this); ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>(); SimpleAdapter adapter = new SimpleAdapter( this, list, R.layout.directory_row, new String[] { "name", "dept" }, new int[] { R.id.name, R.id.dept } ); for (...) { HashMap<String, String> map = new HashMap<String, String>(); map.put("name", name); map.put("dept", dept); list.add(map); } lv.setAdapter(adapter); results.removeAllViews(); results.addView(lv);


Para mí, después de cambiar la información en la base de datos sql, nada podría actualizar la vista de lista (para que sea una vista de lista expandible específica), por lo tanto, si notifyDataSetChanged () no ayuda, puede intentar borrar su lista primero y agregarla nuevamente después de esa llamada notifyDataSetChanged (). Por ejemplo

private List<List<SomeNewArray>> arrayList; List<SomeNewArray> array1= getArrayList(...); List<SomeNewArray> array2= getArrayList(...); arrayList.clear(); arrayList.add(array1); arrayList.add(array2); notifyDataSetChanged();

Espero que tenga sentido para ti.


Si aún no está satisfecho con el Refresco ListView, puede ver este fragmento, esto es para cargar el listView desde DB. En realidad, lo que tiene que hacer es simplemente volver a cargar el ListView, después de realizar cualquier operación CRUD. No es la mejor manera de hacerlo. código, pero actualizará el ListView como desee ..

Funciona para Mí ... si encuentras una solución mejor, por favor comparte ...

....... ...... do your CRUD Operations.. ...... ..... DBAdapter.open(); DBAdapter.insert_into_SingleList(); // Bring that DB_results and add it to list as its contents.... ls2.setAdapter(new ArrayAdapter(DynTABSample.this, android.R.layout.simple_list_item_1, DBAdapter.DB_ListView)); DBAdapter.close();


Si desea actualizar la vista de lista de UI desde un servicio, haga que el adaptador sea estático en su actividad principal y haga esto:

@Override public void onDestroy() { if (MainActivity.isInFront == true) { if (MainActivity.adapter != null) { MainActivity.adapter.notifyDataSetChanged(); } MainActivity.listView.setAdapter(MainActivity.adapter); } }


Si desea mantener su posición de desplazamiento cuando actualiza, y puede hacer esto:

if (mEventListView.getAdapter() == null) { EventLogAdapter eventLogAdapter = new EventLogAdapter(mContext, events); mEventListView.setAdapter(eventLogAdapter); } else { ((EventLogAdapter)mEventListView.getAdapter()).refill(events); } public void refill(List<EventLog> events) { mEvents.clear(); mEvents.addAll(events); notifyDataSetChanged(); }

Para obtener información detallada, consulte ListView de Android: mantenga su posición de desplazamiento cuando actualice .


Si está siguiendo las líneas de la guía de Android y está utilizando los ContentProviders de ContentProviders para obtener datos de la Database de Database y los está mostrando en el ListView utilizando el CursorLoader y los CursorAdapters , entonces todos los cambios en los datos relacionados se reflejarán automáticamente en el ListView.

Su getContext().getContentResolver().notifyChange(uri, null); en el cursor en ContentProvider será suficiente para reflejar los cambios. No es necesario trabajar alrededor.

Pero cuando no está utilizando todo esto, entonces necesita decirle al adaptador cuando el conjunto de datos está cambiando. También debe volver a llenar / recargar su conjunto de datos (por ejemplo, la lista) y luego debe llamar a notifyDataSetChanged() en el adaptador.

notifyDataSetChanged() no funcionará si no hay cambios en el conjunto de datos. Aquí está el comentario sobre el método en docs-

/** * Notifies the attached observers that the underlying data has been changed * and any View reflecting the data set should refresh itself. */



Si hablé sobre mi situación aquí, no funcionó ninguna de las respuestas anteriores porque tuve actividad que muestra la lista de valores de db junto con un botón de eliminación y cuando se presiona un botón de eliminación, quería eliminar ese elemento de la lista.

Lo bueno fue que no usé la vista de reciclador sino una vista de lista simple y esa vista de lista se inicializó en la clase de adaptador. Por lo tanto, llamar a notifyDataSetChanged() no hará nada dentro de la clase de adaptador e incluso en la clase de actividad donde el objeto del adaptador se inicializa porque el método de eliminación estaba en la clase del adaptador.

Por lo tanto, la solución fue eliminar el objeto del adaptador en el método getView clase de adaptador (para eliminar solo ese objeto específico, pero si desea eliminar todo, llame a clear() ).

Para que tengas una idea, ¿cómo era mi código?

public class WordAdapter extends ArrayAdapter<Word> { Context context; public WordAdapter(Activity context, ArrayList<Word> words) {} //....... @NonNull @Override public View getView(final int position, View convertView, ViewGroup group) { //....... ImageButton deleteBt = listItemView.findViewById(R.id.word_delete_bt); deleteBt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (vocabDb.deleteWord(currentWord.id)) { //..... } else{ //..... } remove(getItem(position)); // <---- here is the trick ---< //clear() // if you want to clear everything } }); //....

Nota: aquí los métodos remove() y getItem() se heredan de la clase Adapter.

  • remove() - para eliminar el elemento específico en el que se hace clic
  • getItem(position) : es para obtener el elemento (aquí, ese es mi objeto de Word que he agregado a la lista) desde la posición en la que se hizo clic.

Así es como configuro el adaptador a la vista de lista en la clase de actividad,

ArrayList<Word> wordList = new ArrayList(); WordAdapter adapter = new WordAdapter(this, wordList); ListView list_view = (ListView) findViewById(R.id.activity_view_words); list_view.setAdapter(adapter);


Simplemente use myArrayList.remove(position); dentro de un oyente:

myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, android.view.View view, int position, long id) { myArrayList.remove(position); myArrayAdapter.notifyDataSetChanged(); } });


Solo pude obtener NotifyDataSetChanged solo obteniendo nuevos datos del adaptador, luego restableciendo el adaptador para la vista de lista, y luego haciendo la llamada así:

expandableAdapter = baseFragmentParent.setupEXLVAdapter(); baseFragmentParent.setAdapter(expandableAdapter); expandableAdapter.notifyDataSetChanged();


También puedes usar esto:

myListView.invalidateViews();

¡disfrutar!


Tenía una ArrayList que quería mostrar en una vista de lista. ArrayList contenía elementos de mysql. Anulé el método onRefresh y en ese método usé tablelayout.removeAllViews (); y luego repitió el proceso para obtener datos nuevamente de la base de datos. Pero antes de eso, asegúrese de borrar su ArrayList o cualquier estructura de datos, o si no, los nuevos datos se agregarán a la antigua.


Tenga en cuenta que ha pasado una lista a su adaptador.
Utilizar:

list.getAdapter().notifyDataSetChanged()

para actualizar su lista.


Tengo algunos problemas con la actualización dinámica de mi vista de lista.

Llame a notifyDataSetChanged () en su adaptador.

En este video de Google I / O se pueden ver algunos detalles adicionales sobre cómo / cuándo llamar a NotifyDataSetChanged ().

notifyDataSetChanged () no funcionó correctamente en mi caso [llamé a notifyDataSetChanged de otra clase]. Solo en el caso de que edité el ListView en la Actividad en ejecución (Hilo). Ese video gracias a Christopher dio la pista final.

En mi segunda clase utilicé

Runnable run = new Runnable(){ public void run(){ contactsActivity.update(); } }; contactsActivity.runOnUiThread(run);

para acceder a la actualización () desde mi actividad. Esta actualización incluye

myAdapter.notifyDataSetChanged();

para decirle al adaptador para actualizar la vista. Funcionó bien por lo que puedo decir.


en otra opción está el método onWindowFocusChanged , pero seguro que es sensible y necesita un código adicional para quien esté interesado

override fun onWindowFocusChanged(hasFocus: Boolean) { super.onWindowFocusChanged(hasFocus) // some controls needed programList = usersDBHelper.readProgram(model.title!!) notesAdapter = DailyAdapter(this, programList) notesAdapter.notifyDataSetChanged() listview_act_daily.adapter = notesAdapter }


mientras se usa SimpleCursorAdapter puede llamar a changeCursor (newCursor) en el adaptador.