1c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay/*
2c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Copyright (C) 2017 The Android Open Source Project
3c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay *
4c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Licensed under the Apache License, Version 2.0 (the "License");
5c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * you may not use this file except in compliance with the License.
6c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * You may obtain a copy of the License at
7c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay *
8c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay *      http://www.apache.org/licenses/LICENSE-2.0
9c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay *
10c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Unless required by applicable law or agreed to in writing, software
11c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * distributed under the License is distributed on an "AS IS" BASIS,
12c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * See the License for the specific language governing permissions and
14c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * limitations under the License.
15c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */
16c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
17c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKaypackage android.support.content;
18c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
19c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport static android.support.v4.util.Preconditions.checkArgument;
20c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
21c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.app.LoaderManager;
22c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.app.LoaderManager.LoaderCallbacks;
23c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.content.Context;
24c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.content.Loader;
25c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.database.Cursor;
26c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.os.Bundle;
27c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.support.annotation.NonNull;
28c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.util.Log;
29c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
30c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay/**
31c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * A {@link ContentPager.QueryRunner} that executes queries using a {@link LoaderManager}.
32c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Use this when preparing {@link ContentPager} to run in an Activity or Fragment scope.
33c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */
34c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKaypublic final class LoaderQueryRunner implements ContentPager.QueryRunner {
35c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
36c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    private static final boolean DEBUG = false;
37c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    private static final String TAG = "LoaderQueryRunner";
38c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    private static final String CONTENT_URI_KEY = "contentUri";
39c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
40c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    private final Context mContext;
41c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    private final LoaderManager mLoaderMgr;
42c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
43c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public LoaderQueryRunner(@NonNull Context context, @NonNull LoaderManager loaderMgr) {
44c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mContext = context;
45c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mLoaderMgr = loaderMgr;
46c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
47c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
48c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Override
49c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @SuppressWarnings("unchecked")  // feels spurious. But can't commit line :80 w/o this.
50c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public void query(final @NonNull Query query, @NonNull final Callback callback) {
51c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        if (DEBUG) Log.d(TAG, "Handling query: " + query);
52c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
53c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        LoaderCallbacks callbacks = new LoaderCallbacks<Cursor>() {
54c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            @Override
55c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
56c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                if (DEBUG) Log.i(TAG, "Loading results for query: " + query);
57c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                checkArgument(id == query.getId(), "Id doesn't match query id.");
58c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
59c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                return new android.content.CursorLoader(mContext) {
60c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                    @Override
61c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                    public Cursor loadInBackground() {
62c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                        return callback.runQueryInBackground(query);
63c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                    }
64c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                };
65c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            }
66c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
67c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            @Override
68c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
69c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                if (DEBUG) Log.i(TAG, "Finished loading: " + query);
70c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                mLoaderMgr.destroyLoader(query.getId());
71c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                callback.onQueryFinished(query, cursor);
72c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            }
73c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
74c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            @Override
75c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            public void onLoaderReset(Loader<Cursor> loader) {
76c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                if (DEBUG) Log.w(TAG, "Ignoring loader reset for query: " + query);
77c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            }
78c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        };
79c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
80c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mLoaderMgr.restartLoader(query.getId(), null, callbacks);
81c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
82c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
83c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Override
84c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public boolean isRunning(@NonNull Query query) {
85c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Loader<Cursor> loader = mLoaderMgr.getLoader(query.getId());
86c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        return loader != null && loader.isStarted();
87c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // Hmm, when exactly would the loader not be started? Does it imply that it will
88c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // be starting at some point?
89c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
90c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
91c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Override
92c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public void cancel(@NonNull Query query) {
93c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mLoaderMgr.destroyLoader(query.getId());
94c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
95c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay}
96