107 votes

CursorLoader d’utilisation sans ContentProvider

Android SDK documentation dit que startManagingCursor() méthode est depracated:

Cette méthode est obsolète. L'utilisation de la nouvelle CursorLoader classe avec LoaderManager; ce qui est également disponible sur les anciennes plates-formes sur Android package de compatibilité. Cette méthode permet à l'activité de prendre soin de la gestion de la donnée Curseur du cycle de vie pour vous en fonction de l'activité du cycle de vie. C'est, lorsque l'activité est arrêtée il appelle automatiquement désactiver() sur le Curseur, et lorsqu'il est redémarré plus tard il fera appel requery() pour vous. Lorsque l'activité est détruite, tous gérés Curseurs sera fermé automatiquement. Si vous ciblez en NID d'abeille ou plus tard, pensez plutôt à l'aide de LoaderManager au lieu de cela, disponible via getLoaderManager()

Je voudrais donc utiliser CursorLoader. Mais comment puis-je l'utiliser avec des personnalisés CursorAdapter et sans ContentProvider, quand j'ai besoin d'URI dans le constructeur de CursorLoader?

154voto

Cristian Points 92147

J'ai écrit un simple CursorLoader qui n'a pas besoin d'un fournisseur de contenu:

import android.content.Context;
import android.database.Cursor;
import android.support.v4.content.AsyncTaskLoader;

/**
 * Used to write apps that run on platforms prior to Android 3.0. When running
 * on Android 3.0 or above, this implementation is still used; it does not try
 * to switch to the framework's implementation. See the framework SDK
 * documentation for a class overview.
 *
 * This was based on the CursorLoader class
 */
public abstract class SimpleCursorLoader extends AsyncTaskLoader<Cursor> {
    private Cursor mCursor;

    public SimpleCursorLoader(Context context) {
        super(context);
    }

    /* Runs on a worker thread */
    @Override
    public abstract Cursor loadInBackground();

    /* Runs on the UI thread */
    @Override
    public void deliverResult(Cursor cursor) {
        if (isReset()) {
            // An async query came in while the loader is stopped
            if (cursor != null) {
                cursor.close();
            }
            return;
        }
        Cursor oldCursor = mCursor;
        mCursor = cursor;

        if (isStarted()) {
            super.deliverResult(cursor);
        }

        if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
            oldCursor.close();
        }
    }

    /**
     * Starts an asynchronous load of the contacts list data. When the result is ready the callbacks
     * will be called on the UI thread. If a previous load has been completed and is still valid
     * the result may be passed to the callbacks immediately.
     * <p/>
     * Must be called from the UI thread
     */
    @Override
    protected void onStartLoading() {
        if (mCursor != null) {
            deliverResult(mCursor);
        }
        if (takeContentChanged() || mCursor == null) {
            forceLoad();
        }
    }

    /**
     * Must be called from the UI thread
     */
    @Override
    protected void onStopLoading() {
        // Attempt to cancel the current load task if possible.
        cancelLoad();
    }

    @Override
    public void onCanceled(Cursor cursor) {
        if (cursor != null && !cursor.isClosed()) {
            cursor.close();
        }
    }

    @Override
    protected void onReset() {
        super.onReset();

        // Ensure the loader is stopped
        onStopLoading();

        if (mCursor != null && !mCursor.isClosed()) {
            mCursor.close();
        }
        mCursor = null;
    }
}

Il a besoin seulement de l' AsyncTaskLoader classe. L'un dans Android 3.0 ou supérieur, ou celui qui est livré avec le package de compatibilité.

J'ai aussi écrit un ListLoader qui est compatible avec l' LoadManager et est utilisée pour récupérer un générique java.util.List de la collecte.

22voto

Nikolay Elenkov Points 32843

Écrivez votre propre chargeur qui utilise votre classe de base de données au lieu d’un fournisseur de contenu. La plus simple consiste simplement à prendre la source de la `` classe de la bibliothèque de compatibilité et remplacer les requêtes de fournisseur avec requêtes à votre propre classe d’assistance de db.

14voto

emmby Points 35359

Le SimpleCursorLoader est une solution simple, mais il ne supporte pas mise à jour le chargeur lorsque les données changent. CommonsWare dispose d’une bibliothèque de loaderex qui ajoute une SQLiteCursorLoader et prend en charge ré-interroger sur la modification des données.

https://github.com/commonsguy/CWAC-loaderex

12voto

Timo Ohr Points 5550

Une troisième option serait de tout simplement ignorer loadInBackground:

public class CustomCursorLoader extends CursorLoader {
    private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();

    @Override
    public Cursor loadInBackground() {
        Cursor cursor = ... // get your cursor from wherever you like

        if (cursor != null) {
            // Ensure the cursor window is filled
            cursor.getCount();
            cursor.registerContentObserver(mObserver);
        }

        return cursor;
    }
};

Cela permettra également de prendre soin de ré-interrogation de votre curseur lorsque les modifications de base de données.

Seul inconvénient: Vous devrez définir un autre observateur, puisque Google dans son infinie sagesse, a décidé de faire de leur colis privé. Si vous mettez de la classe dans le même emballage que celui d'origine (ou la compat un), vous pouvez en fait utiliser l'original de l'observateur. L'observateur est une très légère objet et n'est pas utilisé ailleurs, donc ce n'est pas beaucoup de différence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X