【问题标题】:Android: restart CursorLoader on content changedAndroid:在内容更改时重新启动 CursorLoader
【发布时间】:2015-07-18 10:16:53
【问题描述】:

我正在使用 LoaderManagerCursorLoader 以异步方式将数据从我的 ContentProvider 加载到 GUI。一切正常。但是我想知道一旦 ContentProvider 的内容发生了变化,如何重新启动加载器?据我研究,CursorLoader 应该自动执行此操作,但在我的情况下它不会!那么,我应该注册一个内容观察者并重新启动 LoaderManager 吗?

注意: ContentProvider 已正确实现。例如,如果插入了一个新项目,我将使用主 URI 和新插入项目的 URI 调用 ContentProvider.notifyChange(...)。对于 ContentObservers 这工作正常。

public class MyFragment implements LoaderManager.LoaderCallbacks<Cursor> {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_sample, container, false);
        getLoaderManager().initLoader(1, null, this);
        return view;
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        if (isDetached())
            return null;

        Uri queryUri = MyContentProvider.CONTENT_URI;
        String[] projection = this.getProjection();
        String selection = null;
        String[] selectionArgs = null;
        String sortOrder = null;

        return new CursorLoader(getActivity(), queryUri, projection, selection, selectionArgs, sortOrder);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        // ToDo: display the content (in this case it's not a ListView but a Google Map with markers)

        // Remark: I'm using the data/cursor only, but I'm not holding the loader!
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        // ToDo: clear/remove all markers from the map
    }
}

【问题讨论】:

    标签: android android-contentprovider android-cursorloader contentobserver


    【解决方案1】:

    在您的提供商的查询方法中检查是否在您的光标中设置了通知 uri,然后再返回它。

        @Override
        public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
            int match = mUriMatcher.match(uri);
            SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();
            ContentResolver contentResolver = getContext().getContentResolver();
            Cursor cursor;
            switch (match) {
                case ROUTE_POSITIONS:
                    cursor = db.query(DatabaseContract.PositionEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
                    cursor.setNotificationUri(contentResolver, DatabaseContract.PositionEntry.CONTENT_URI);
                    break;
                // do more cases ....
                default:
                    throw new UnsupportedOperationException("Unknow uri: " + uri);
            }
            return cursor;
        }
    

    在您的活动之后,您可以定义一个异步任务以在地图中加载数据

    private class LoadMarkers extends AsyncTask<Cursor, MarkerOptions, String>{
    
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mMap.clear();
        }
    
        @Override
        protected String doInBackground(Cursor... params) {
            Cursor data = params[0];
            LatLng latLng = null;
            while (data.moveToNext()) {
                double latitude = data.getDouble(data.getColumnIndex(DatabaseContract.PositionEntry.COLUMN_NAME_LATITUDE));
                double longitude = data.getDouble(data.getColumnIndex(DatabaseContract.PositionEntry.COLUMN_NAME_LONGITUDE));
                String date = data.getString(data.getColumnIndex(DatabaseContract.PositionEntry.COLUMN_NAME_UPDATETIME));
                latLng = new LatLng(latitude, longitude);
                MarkerOptions markerOptions = new MarkerOptions().title(date).position(latLng);
                publishProgress(markerOptions);
                Log.d(TAG, "Loading...");
            }
            int count = data .getCount();
            return count + " points";
        }
    
        @Override
        protected void onProgressUpdate(MarkerOptions... values) {
            super.onProgressUpdate(values);
            MarkerOptions markerOptions = values[0];
            mMap.addMarker(markerOptions);
        }
    
        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            mTextView.setText(result);
        }
    }
    

    并在新查询准备好时执行

    @Override
    public void onLoadFinished(android.support.v4.content.Loader<Cursor> loader, Cursor data) {
        Log.d(TAG, "data loaded: " + data.getCount() + " points");
        new LoadMarkers().execute(data);
    }
    

    【讨论】:

    • 感谢您的提示。我就是这样做的。光标上的参数是正确的。但我现在使用的是 LoaderManager 而不是 AsncTask。您的代码也不会自动更新。这只是一次通话。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    • 2020-01-21
    • 2020-02-13
    相关资源
    最近更新 更多