源数据更改时加载器不加载数据

发布于 2024-12-08 02:49:34 字数 4320 浏览 2 评论 0原文

Android 文档指出 LOADERS - 它们监视数据源并在内容更改时提供新结果。我已更改 CursorAdapter 以适用于 SQLite 数据库。

import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader.ForceLoadContentObserver;
import android.util.Log;


public class SimpleCursorLoader extends AsyncTaskLoader<Cursor> {

final ForceLoadContentObserver mObserver;

String mTable;
String[] mColumns;
String mSelection;
String[] mSelectionArgs;
String mGroupBy;
String mHaving;
String mOrderBy;
String mLimit;

Cursor mCursor;
SQLiteDatabase mDb;
 /**
 * Creates an empty unspecified CursorLoader.  You must follow this with
 * calls to {@link #setUri(Uri)}, {@link #setSelection(String)}, etc
 * to specify the query to perform.
 */
public SimpleCursorLoader(Context context) {
    super(context);
    mObserver = new ForceLoadContentObserver();
}

/**
 * Creates a fully-specified SimpleCursorLoader.  See
 * {@link ContentResolver#query(Uri, String[], String, String[], String)
 * ContentResolver.query()} for documentation on the meaning of the
 * parameters.  These will be passed as-is to that call.
 */
public SimpleCursorLoader(Context context,String table, String[] columns, String      selection, 
        String[] selectionArgs, String groupBy, String having, String orderBy, String limit, SQLiteDatabase db) {

    super(context);
    mObserver = new ForceLoadContentObserver();
    mTable = table;
    mColumns = columns; //copying array
    mSelection = selection;
    mSelectionArgs = selectionArgs;
    mGroupBy = groupBy;
    mHaving = having;
    mOrderBy =  orderBy;
    mLimit = limit;
    mDb = db;
}       

    /* Runs on a worker thread */
@Override
public Cursor loadInBackground() {
    Cursor cursor = mDb.query(mTable, mColumns, mSelection, mSelectionArgs, mGroupBy, mHaving, mOrderBy, mLimit);
    if (cursor != null) {
        // Ensure the cursor window is filled
        cursor.getCount();
        Log.d("SimpleCursorLoader","Cursor.getCount()= " + String.valueOf(cursor.getCount()));
        registerContentObserver(cursor, mObserver);
    }
    return cursor;
}

/**
 * Registers an observer to get notifications from the content provider
 * when the cursor needs to be refreshed.
 */
void registerContentObserver(Cursor cursor, ContentObserver observer) {
    cursor.registerContentObserver(mObserver);
}

/* Runs on the UI thread */
@Override
public void deliverResult(Cursor cursor) {
    Log.d("Gaurav","Inside SimpleCursorLoader - deliverResult");
    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.
 *
 * Must be called from the UI thread
 */
@Override
protected void onStartLoading() {
    Log.d("Gaurav", "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;
}

}

CursorLoader 在带有自定义适配器的 ListFragment 中工作,该适配器扩展了 SimpleCursor Adapter 并在构造函数中传递 FLAG_REGISTER_CONTENT_OBSERVER,但当列表中使用的响应更改基础数据时,游标会发生变化。

Android Documentation states that LOADERS - They monitor the source of their data and deliver new results when the content changes. I have changed CursorAdapter to work for a SQLite Database.

import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader.ForceLoadContentObserver;
import android.util.Log;


public class SimpleCursorLoader extends AsyncTaskLoader<Cursor> {

final ForceLoadContentObserver mObserver;

String mTable;
String[] mColumns;
String mSelection;
String[] mSelectionArgs;
String mGroupBy;
String mHaving;
String mOrderBy;
String mLimit;

Cursor mCursor;
SQLiteDatabase mDb;
 /**
 * Creates an empty unspecified CursorLoader.  You must follow this with
 * calls to {@link #setUri(Uri)}, {@link #setSelection(String)}, etc
 * to specify the query to perform.
 */
public SimpleCursorLoader(Context context) {
    super(context);
    mObserver = new ForceLoadContentObserver();
}

/**
 * Creates a fully-specified SimpleCursorLoader.  See
 * {@link ContentResolver#query(Uri, String[], String, String[], String)
 * ContentResolver.query()} for documentation on the meaning of the
 * parameters.  These will be passed as-is to that call.
 */
public SimpleCursorLoader(Context context,String table, String[] columns, String      selection, 
        String[] selectionArgs, String groupBy, String having, String orderBy, String limit, SQLiteDatabase db) {

    super(context);
    mObserver = new ForceLoadContentObserver();
    mTable = table;
    mColumns = columns; //copying array
    mSelection = selection;
    mSelectionArgs = selectionArgs;
    mGroupBy = groupBy;
    mHaving = having;
    mOrderBy =  orderBy;
    mLimit = limit;
    mDb = db;
}       

    /* Runs on a worker thread */
@Override
public Cursor loadInBackground() {
    Cursor cursor = mDb.query(mTable, mColumns, mSelection, mSelectionArgs, mGroupBy, mHaving, mOrderBy, mLimit);
    if (cursor != null) {
        // Ensure the cursor window is filled
        cursor.getCount();
        Log.d("SimpleCursorLoader","Cursor.getCount()= " + String.valueOf(cursor.getCount()));
        registerContentObserver(cursor, mObserver);
    }
    return cursor;
}

/**
 * Registers an observer to get notifications from the content provider
 * when the cursor needs to be refreshed.
 */
void registerContentObserver(Cursor cursor, ContentObserver observer) {
    cursor.registerContentObserver(mObserver);
}

/* Runs on the UI thread */
@Override
public void deliverResult(Cursor cursor) {
    Log.d("Gaurav","Inside SimpleCursorLoader - deliverResult");
    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.
 *
 * Must be called from the UI thread
 */
@Override
protected void onStartLoading() {
    Log.d("Gaurav", "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;
}

}

The CursorLoader works in a ListFragment with a custom adapter which extends SimpleCursor Adapter and passes FLAG_REGISTER_CONTENT_OBSERVER in constructor but the cursor does changes when underlying data is changed by used response in the list.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

话少情深 2024-12-15 02:49:34

我遇到了同样的问题,尽管我使用的实现与你不同。我能够通过将通知 URI 明确指定为不太具体的内容来纠正我的问题。我确信我的代码还存在其他问题,导致我需要这样做,但它解决了我的问题。因此,我的内容提供程序中的游标查询从:

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,  String sortOrder) {

................
................
................

Cursor cursor = queryBuilder.query(mDB.getReadableDatabase(),
                projection, selection, selectionArgs, null, null, sortOrder);
                cursor.setNotificationUri(getContext().getContentResolver(), uri);
cursor.setNotificationUri(getContext().getContentResolver(), uri;)

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,  String sortOrder) {

................
................
................

Cursor cursor = queryBuilder.query(mDB.getReadableDatabase(),
                projection, selection, selectionArgs, null, null, sortOrder);
                cursor.setNotificationUri(getContext().getContentResolver(), uri);
cursor.setNotificationUri(getContext().getContentResolver(), MYURI;)

MYURI 是 URI 类型的变量,我知道该变量将涵盖我正在观看的所有内容。

希望这可以帮助别人。

I had the same problem albeit I was using a different implementation than you. I was able to correct my problem by explicitly stating notification URI to something less specific. I'm sure there are other problems with my code that caused me to need to do this but it fixed my issue. So, my Cursor query in my content provider went from:

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,  String sortOrder) {

................
................
................

Cursor cursor = queryBuilder.query(mDB.getReadableDatabase(),
                projection, selection, selectionArgs, null, null, sortOrder);
                cursor.setNotificationUri(getContext().getContentResolver(), uri);
cursor.setNotificationUri(getContext().getContentResolver(), uri;)

to

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,  String sortOrder) {

................
................
................

Cursor cursor = queryBuilder.query(mDB.getReadableDatabase(),
                projection, selection, selectionArgs, null, null, sortOrder);
                cursor.setNotificationUri(getContext().getContentResolver(), uri);
cursor.setNotificationUri(getContext().getContentResolver(), MYURI;)

where MYURI is variable of the URI type that I know will cover everything I'm watching.

Hope this helps someone out.

病女 2024-12-15 02:49:34

您需要重写转储方法。

@Override
    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
        super.dump(prefix, fd, writer, args);
        writer.print(prefix); writer.print("mTable="); writer.println(mTable);
        writer.print(prefix); writer.print("mDB=");writer.println(mDb);
        writer.print(prefix); writer.print("mProjection=");
                writer.println(Arrays.toString(mProjection));
        writer.print(prefix); writer.print("mSelection="); writer.println(mSelection);
        writer.print(prefix); writer.print("mSelectionArgs=");
                writer.println(Arrays.toString(mSelectionArgs));
        writer.print(prefix); writer.print("mSortOrder="); writer.println(mSortOrder);
        writer.print(prefix); writer.print("mCursor="); writer.println(mCursor);
        writer.print(prefix); writer.print("mContentChanged="); writer.println(mContentChanged);
    }

You need to override the dump method.

@Override
    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
        super.dump(prefix, fd, writer, args);
        writer.print(prefix); writer.print("mTable="); writer.println(mTable);
        writer.print(prefix); writer.print("mDB=");writer.println(mDb);
        writer.print(prefix); writer.print("mProjection=");
                writer.println(Arrays.toString(mProjection));
        writer.print(prefix); writer.print("mSelection="); writer.println(mSelection);
        writer.print(prefix); writer.print("mSelectionArgs=");
                writer.println(Arrays.toString(mSelectionArgs));
        writer.print(prefix); writer.print("mSortOrder="); writer.println(mSortOrder);
        writer.print(prefix); writer.print("mCursor="); writer.println(mCursor);
        writer.print(prefix); writer.print("mContentChanged="); writer.println(mContentChanged);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文