【问题标题】:notifyChange not updating UI when using CursorRecyclerViewAdapter使用 CursorRecyclerViewAdapter 时 notifyChange 不更新 UI
【发布时间】:2015-06-03 15:30:05
【问题描述】:

Android 不提供与 recyclerView 一起使用的 CursorAdapter。

我曾尝试使用此处找到的 CursorRecyclerViewAdapter: https://gist.github.com/skyfishjy/443b7448f59be978bc59

当我从 ContentProvider 调用 notifyChange 时, 观察者没有被调用。

~SNIP 我的片段/控制器....

 //adapter
        mAdapter = new CursorRecyclerViewAdapter(getActivity(), null,true) {
            @Override
            public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, Cursor cursor) {
            ((WidgetAdapter.ViewHolder)viewHolder).setTitle(cursor.getString(4)  + "  id: " + cursor.getInt(0) + " order: " + cursor.getInt(15));
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
            Context context = viewGroup.getContext();
            View parent = LayoutInflater.from(context).inflate(R.layout.ned_apps_order_item, viewGroup, false);
            return WidgetAdapter.ViewHolder.newInstance(parent);
        }

    };

    mRecyclerView.setAdapter(mAdapter);

~SNIP - 加载程序回调

@Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
        String parent_id = bundle == null ? "0" : "" + bundle.getInt(PARENT_ID);
        String PARENT_SELECTION = PARENT_ID + "= ?";

        return new CursorLoader(getActivity(), Schema.CONTENT_URI,null,
                PARENT_SELECTION,new String[] {parent_id}, "_order ASC");
    }

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    mAdapter.swapCursor(cursor);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    mAdapter.swapCursor(null);
}

~截图

~SNIP~ my Provider.....
 @Override
    public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) {

        String modifiedSelection = selection;

        switch (uriMatcher.match(uri)) {
            case WIDGET_ID: {
                modifiedSelection += " = " + uri.getLastPathSegment();
                System.out.println(">>"+modifiedSelection);
            }
        }

        int updateCount = 0;
        updateCount = database.update(Schema.Table.TABLE_NAME,contentValues,modifiedSelection,null);



        if (updateCount == 1) {
            getContext().getContentResolver().notifyChange(uri,null);
        }

        return updateCount;
    }
~SNIP~

~SNIP - skyfishjy

import android.content.Context;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.support.v7.widget.RecyclerView;

/**
 * Created by skyfishjy on 10/31/14.
 */

public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {

    private Context mContext;

    private Cursor mCursor;

    private boolean mDataValid;

    private int mRowIdColumn;

    private DataSetObserver mDataSetObserver;

    public CursorRecyclerViewAdapter(Context context, Cursor cursor,boolean hasStableIds) {
        mContext = context;
        mCursor = cursor;
        mDataValid = cursor != null;
        mRowIdColumn = mDataValid ? mCursor.getColumnIndex("_id") : -1;
        mDataSetObserver = new NotifyingDataSetObserver();
        if (mCursor != null) {
            mCursor.registerDataSetObserver(mDataSetObserver);
        }
        super.setHasStableIds(hasStableIds);
    }

    public Cursor getCursor() {
        return mCursor;
    }


    @Override
    public int getItemCount() {
        if (mDataValid && mCursor != null) {
            return mCursor.getCount();
        }
        return 0;
    }

    @Override
    public long getItemId(int position) {
        if (mDataValid && mCursor != null && mCursor.moveToPosition(position)) {
            return mCursor.getLong(mRowIdColumn);
        }
        return 0;
    }

    @Override
    public void setHasStableIds(boolean hasStableIds) {
        super.setHasStableIds(true);
    }

    public abstract void onBindViewHolder(VH viewHolder, Cursor cursor);

    @Override
    public void onBindViewHolder(VH viewHolder, int position) {
        if (!mDataValid) {
            throw new IllegalStateException("this should only be called when the cursor is valid");
        }
        if (!mCursor.moveToPosition(position)) {
            throw new IllegalStateException("couldn't move cursor to position " + position);
        }
        onBindViewHolder(viewHolder, mCursor);
    }

    /**
     * Change the underlying cursor to a new cursor. If there is an existing cursor it will be
     * closed.
     */
    public void changeCursor(Cursor cursor) {
        Cursor old = swapCursor(cursor);
        if (old != null) {
            old.close();
        }
    }

    /**
     * Swap in a new Cursor, returning the old Cursor.  Unlike
     * {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em>
     * closed.
     */
    public Cursor swapCursor(Cursor newCursor) {
        if (newCursor == mCursor) {
            return null;
        }
        final Cursor oldCursor = mCursor;
        if (oldCursor != null && mDataSetObserver != null) {
            oldCursor.unregisterDataSetObserver(mDataSetObserver);
        }
        mCursor = newCursor;
        if (mCursor != null) {
            if (mDataSetObserver != null) {
                mCursor.registerDataSetObserver(mDataSetObserver);
            }
            mRowIdColumn = newCursor.getColumnIndexOrThrow("_id");
            mDataValid = true;
            notifyDataSetChanged();
        } else {
            mRowIdColumn = -1;
            mDataValid = false;
            notifyDataSetChanged();
            //There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
        }
        return oldCursor;
    }

    public int getPositionForId(long id) {

        mCursor.moveToFirst();

        while (mCursor.moveToNext()) {
            if (mCursor.getInt(0) == id) {
                return mCursor.getInt(15);
            }
        }

        return -1;
    }


    private class NotifyingDataSetObserver extends DataSetObserver {
        @Override
        public void onChanged() {
            super.onChanged();
            mDataValid = true;
            notifyDataSetChanged();
        }

        @Override
        public void onInvalidated() {
            super.onInvalidated();
            mDataValid = false;
            notifyDataSetChanged();
            //There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
        }
    }
}

【问题讨论】:

    标签: android android-contentprovider android-adapter android-recyclerview


    【解决方案1】:

    我发现了问题,它没有在我的代码中列出 问题。

    @Override
        public Cursor query(final Uri uri, final String[] projection,
                            final String selection, final String[] selectionArgs,
                            final String sortOrder) {
    
            Log.d(TAG, "query()" + uri.toString());
    
            String modifiedSelection = selection;
    
            switch (uriMatcher.match(uri)) {
    
                case WIDGET_ID: {
                    modifiedSelection += SchemaTable.ID
                            + " = " + uri.getLastPathSegment();
                    break;
                }
    
                case WIDGETS: {
                    //return database.query(Schema.Table.TABLE_NAME, WidgetModel.getAllColumns(), selection, selectionArgs, null, null, sortOrder);
                    break;
                }
    
                default: {
                    //TODO log only when this is a debug build
                    throw new IllegalArgumentException("Unknown URI: " + uri);
                }
            }
    
            return database.query(Schema.Table.TABLE_NAME,WidgetModel.getAllColumns(), modifiedSelection, selectionArgs, null, null, sortOrder); 
        }
    

    缺少这一行:

    ....setNotificationUri(getContext().getContentResolver(),uri);
    

    然后固定的代码是用这个代码替换return语句:

    Cursor cursor = database.query(Schema.Table.TABLE_NAME, WidgetModel.getAllColumns(), modifiedSelection, selectionArgs, null, null, sortOrder);
                cursor.setNotificationUri(getContext().getContentResolver(),uri);
                return cursor;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-25
      • 2020-09-15
      • 2018-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多