1cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn/*
2cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Copyright (C) 2011 The Android Open Source Project
3cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
4cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * you may not use this file except in compliance with the License.
6cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * You may obtain a copy of the License at
7cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
8cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
10cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
11cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * See the License for the specific language governing permissions and
14cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * limitations under the License.
15cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */
16cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
17cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornpackage android.support.v4.content;
18cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
19cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.content.Context;
20cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.database.ContentObserver;
21cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.database.Cursor;
22cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.net.Uri;
23cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
24cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.io.FileDescriptor;
25cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.io.PrintWriter;
26cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.util.Arrays;
27cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
28cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn/**
29cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Static library support version of the framework's {@link android.content.CursorLoader}.
30cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Used to write apps that run on platforms prior to Android 3.0.  When running
31cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * on Android 3.0 or above, this implementation is still used; it does not try
32cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * to switch to the framework's implementation.  See the framework SDK
33cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * documentation for a class overview.
34cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */
35cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornpublic class CursorLoader extends AsyncTaskLoader<Cursor> {
36cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    final ForceLoadContentObserver mObserver;
37cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
38cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    Uri mUri;
39cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    String[] mProjection;
40cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    String mSelection;
41cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    String[] mSelectionArgs;
42cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    String mSortOrder;
43cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
44cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    Cursor mCursor;
45cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
46cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /* Runs on a worker thread */
47cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
48cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public Cursor loadInBackground() {
49cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        Cursor cursor = getContext().getContentResolver().query(mUri, mProjection, mSelection,
50cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mSelectionArgs, mSortOrder);
51cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (cursor != null) {
52cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // Ensure the cursor window is filled
53cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            cursor.getCount();
54de2eb627f0c4cb79c78e4d91ae7086d2c5e67eecScott Kennedy            cursor.registerContentObserver(mObserver);
55cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
56cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return cursor;
57cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
58cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
59cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /* Runs on the UI thread */
60cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
61cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void deliverResult(Cursor cursor) {
62cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (isReset()) {
63cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // An async query came in while the loader is stopped
64cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (cursor != null) {
65c286d5c93640e82c649888b7e5045801581e4d6cDianne Hackborn                cursor.close();
66cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
67cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return;
68cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
69cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        Cursor oldCursor = mCursor;
70cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mCursor = cursor;
71cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
72cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (isStarted()) {
73cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            super.deliverResult(cursor);
74cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
75cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
76cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
77c286d5c93640e82c649888b7e5045801581e4d6cDianne Hackborn            oldCursor.close();
78cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
79cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
80cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
81cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
82cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Creates an empty unspecified CursorLoader.  You must follow this with
83cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * calls to {@link #setUri(Uri)}, {@link #setSelection(String)}, etc
84cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * to specify the query to perform.
85cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
86cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public CursorLoader(Context context) {
87cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        super(context);
88cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mObserver = new ForceLoadContentObserver();
89cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
90cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
91cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
92cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Creates a fully-specified CursorLoader.  See
930574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov     * {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
94cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * ContentResolver.query()} for documentation on the meaning of the
95cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * parameters.  These will be passed as-is to that call.
96cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
97cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public CursorLoader(Context context, Uri uri, String[] projection, String selection,
98cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            String[] selectionArgs, String sortOrder) {
99cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        super(context);
100cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mObserver = new ForceLoadContentObserver();
101cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mUri = uri;
102cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mProjection = projection;
103cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mSelection = selection;
104cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mSelectionArgs = selectionArgs;
105cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mSortOrder = sortOrder;
106cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
107cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
108cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
109cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Starts an asynchronous load of the contacts list data. When the result is ready the callbacks
110cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * will be called on the UI thread. If a previous load has been completed and is still valid
111cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * the result may be passed to the callbacks immediately.
112cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
113cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Must be called from the UI thread
114cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
115cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
116cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    protected void onStartLoading() {
117cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mCursor != null) {
118cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            deliverResult(mCursor);
119cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
120cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (takeContentChanged() || mCursor == null) {
121cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            forceLoad();
122cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
123cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
124cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
125cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
126cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Must be called from the UI thread
127cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
128cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
129cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    protected void onStopLoading() {
130cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        // Attempt to cancel the current load task if possible.
131cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        cancelLoad();
132cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
133cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
134cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
135cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void onCanceled(Cursor cursor) {
136cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (cursor != null && !cursor.isClosed()) {
137c286d5c93640e82c649888b7e5045801581e4d6cDianne Hackborn            cursor.close();
138cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
139cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
140cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
141cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
142cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    protected void onReset() {
143cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        super.onReset();
144cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
145cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        // Ensure the loader is stopped
146cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        onStopLoading();
147cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
148cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mCursor != null && !mCursor.isClosed()) {
149c286d5c93640e82c649888b7e5045801581e4d6cDianne Hackborn            mCursor.close();
150cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
151cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mCursor = null;
152cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
153cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
154cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public Uri getUri() {
155cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return mUri;
156cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
157cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
158cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void setUri(Uri uri) {
159cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mUri = uri;
160cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
161cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
162cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public String[] getProjection() {
163cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return mProjection;
164cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
165cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
166cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void setProjection(String[] projection) {
167cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mProjection = projection;
168cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
169cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
170cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public String getSelection() {
171cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return mSelection;
172cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
173cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
174cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void setSelection(String selection) {
175cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mSelection = selection;
176cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
177cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
178cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public String[] getSelectionArgs() {
179cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return mSelectionArgs;
180cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
181cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
182cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void setSelectionArgs(String[] selectionArgs) {
183cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mSelectionArgs = selectionArgs;
184cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
185cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
186cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public String getSortOrder() {
187cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return mSortOrder;
188cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
189cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
190cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void setSortOrder(String sortOrder) {
191cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mSortOrder = sortOrder;
192cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
193cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
194cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
195cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
196cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        super.dump(prefix, fd, writer, args);
197cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        writer.print(prefix); writer.print("mUri="); writer.println(mUri);
198cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        writer.print(prefix); writer.print("mProjection=");
199cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                writer.println(Arrays.toString(mProjection));
200cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        writer.print(prefix); writer.print("mSelection="); writer.println(mSelection);
201cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        writer.print(prefix); writer.print("mSelectionArgs=");
202cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                writer.println(Arrays.toString(mSelectionArgs));
203cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        writer.print(prefix); writer.print("mSortOrder="); writer.println(mSortOrder);
204cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        writer.print(prefix); writer.print("mCursor="); writer.println(mCursor);
205cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        writer.print(prefix); writer.print("mContentChanged="); writer.println(mContentChanged);
206cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
207cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn}
208