viernes, 3 de octubre de 2014

Vistas de tipo lista

Una vista de tipo ListView es una vista de grupo que muestra un listado de elementos permitiendo desplazamiento de pantalla. Los elementos se añaden y se actualizan de manera automática a la lista a través de un adaptador Adapter. El adaptador se encargará de construir la vista para cada elemento y añadirla a la lista. Para ello, el adaptador utilizará una fuente de datos (un array o el cursor resultado de una consulta, por ejemplo) y de una plantilla auxiliar.


Usando un cargador.

Un cargador de tipo CursorLoader es la manera habitual de obtener los datos de manera asíncrona sin llegar a bloquear la hebra principal de nuestra aplicación. Cuando el cargador recibe los resultados de una consulta, el sistema llamará al método onLoadFinish() desde donde actualizaremos nuestro adaptador con los resultados y éste, a su vez, los mostrará por pantalla.

Aunque la clase CursorLoader se introdujo a partir de la versión 3.0 de Android (versión 11 de la API), se puede usar a través de la biblioteca de soporte, por lo que podremos utilizar esta clase para dispositivos con versiones de Android 1.6 o superior.

Ejemplo.

El el siguiente ejemplo utilizaremos una actividad de tipo ListActivity que incluye por defecto una plantilla cuyo único elemento es una vista de tipo ListView donde mostraremos un listado con los contactos de nuestro dispositivo.

La actividad implementa la interfaz LoaderCallbacks con el fin de utilizar un cargador de tipo CursorLoader que será el encargado de obtener los datos que serán mostrados en el listado.
public class ListViewLoader extends ListActivity
        implements LoaderManager.LoaderCallbacks {

    // Definimos el adaptador que se encargará de mostrar los datos en la lista.
    SimpleCursorAdapter mAdapter;

    // Definimos la cláusula de proyección de la consulta.
    // Obtendremos el ID y el nombre para cada contacto.
    static final String[] PROJECTION = new String[] {ContactsContract.Data._ID,
            ContactsContract.Data.DISPLAY_NAME};

    // Definimos la cláusula de selección.
    static final String SELECTION = "((" + 
            ContactsContract.Data.DISPLAY_NAME + " NOTNULL) AND (" +
            ContactsContract.Data.DISPLAY_NAME + " != '' ))";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Creamos una barra de progreso que se mostrará mientras los datos se cargan.
        ProgressBar progressBar = new ProgressBar(this);
        progressBar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT, Gravity.CENTER));
        progressBar.setIndeterminate(true);
        getListView().setEmptyView(progressBar);

        // Añadimos la barra de progreso al elemento raíz de la plantilla.
        ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
        root.addView(progressBar);

        // Definimos los arrays que utilizará nuestro adaptador.
        // Un array con los nombres de columna.
        // Un array con los identificadores de cada vista.
        String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME};
        int[] toViews = {android.R.id.text1}; // The TextView in simple_list_item_1

        // Creamos el adaptador que mostrará los datos.
        // Inicialmente no tenemos elementos que mostrar hasta que no haga
        // la primera carga (onLoadFinished()).
        mAdapter = new SimpleCursorAdapter(this, 
                android.R.layout.simple_list_item_1, null,
                fromColumns, toViews, 0);
        setListAdapter(mAdapter);

        // Preparamos el cargador. Si no existe se crea. Si ya existe se reutiliza.
        getLoaderManager().initLoader(0, null, this);
    }

    // Se invoca cuando se crear el cargador.
    public Loader onCreateLoader(int id, Bundle args) {
        // Creamos y devolvemos el cursor asociado al proveedor de contactos.
        return new CursorLoader(this, ContactsContract.Data.CONTENT_URI,
                PROJECTION, SELECTION, null, null);
    }

    // Se invoca cuando ha finalizado la carga.
    public void onLoadFinished(Loader loader, Cursor data) {
        // Actualizamos los datos del adaptador con el nuevo resultado.
        // El entorno de trabajo se encargará de liberar los datos antiguos de manera automática.
        mAdapter.swapCursor(data);
    }

    // Se invoca cuando vaciamos el cargador de datos.
    public void onLoaderReset(Loader loader) {
        mAdapter.swapCursor(null);
    }

    @Override 
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Hacemos algo cuando se selecciona un elemento de la lista.
    }
}
Nota. Debido a que en el ejemplo se accede al proveedor de contactos, si queremos probar el código tendremos que dar el permiso de lectura necesario a nuestra aplicación en el archivo manifest:
<uses-permission android:name="android.permission.READ_CONTACTS" />
El proceso se podría resumir en los siguientes pasos:
  1. El cargador solicita los contactos al proveedor de contactos.
  2. El proveedor de contactos obtiene los contactos y los entrega al cargador.
  3. El cargador entrega los contactos al adaptador.
  4. El adaptador actualiza los contactos en la vista.

No hay comentarios:

Publicar un comentario