16b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn/*
26b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn * Copyright (C) 2011 The Android Open Source Project
36b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn *
46b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
56b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn * you may not use this file except in compliance with the License.
66b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn * You may obtain a copy of the License at
76b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn *
86b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
96b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn *
106b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
116b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
126b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn * See the License for the specific language governing permissions and
146b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn * limitations under the License.
156b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn */
166b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1710c33528e033643099783a5bc4eedb4b8a1e9a0eDianne Hackbornpackage com.example.android.supportv4.app;
186b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
196b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn//BEGIN_INCLUDE(complete)
206b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.content.ContentProvider;
216b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.content.ContentResolver;
226b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.content.ContentUris;
236b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.content.ContentValues;
246b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.content.Context;
256b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.content.UriMatcher;
266b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.database.Cursor;
276b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.database.SQLException;
286b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.database.sqlite.SQLiteDatabase;
296b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.database.sqlite.SQLiteOpenHelper;
306b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.database.sqlite.SQLiteQueryBuilder;
316b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.net.Uri;
326b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.os.AsyncTask;
336b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.os.Bundle;
346b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.provider.BaseColumns;
35a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganovimport android.support.v4.app.FragmentActivity;
36a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganovimport android.support.v4.app.FragmentManager;
37a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganovimport android.support.v4.app.ListFragment;
38a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganovimport android.support.v4.app.LoaderManager;
39a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganovimport android.support.v4.content.CursorLoader;
40a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganovimport android.support.v4.content.Loader;
41a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganovimport android.support.v4.database.DatabaseUtilsCompat;
42a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganovimport android.support.v4.view.MenuItemCompat;
43a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganovimport android.support.v4.widget.SimpleCursorAdapter;
446b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.text.TextUtils;
456b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.util.Log;
466b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.view.Menu;
476b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.view.MenuInflater;
486b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.view.MenuItem;
496b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.view.View;
506b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport android.widget.ListView;
516b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
526b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornimport java.util.HashMap;
536b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
546b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn/**
556b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn * Demonstration of bottom to top implementation of a content provider holding
566b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn * structured data through displaying it in the UI, using throttling to reduce
576b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn * the number of queries done when its data changes.
586b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn */
596b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackbornpublic class LoaderThrottleSupport extends FragmentActivity {
606b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    // Debugging.
616b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    static final String TAG = "LoaderThrottle";
626b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
636b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    /**
646b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn     * The authority we use to get to our sample provider.
656b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn     */
667ffb7d4b2face7d2ce5cee82c92ec36fd0ba2932Dianne Hackborn    public static final String AUTHORITY = "com.example.android.apis.supportv4.app.LoaderThrottle";
676b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
686b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    /**
696b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn     * Definition of the contract for the main table of our provider.
706b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn     */
716b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    public static final class MainTable implements BaseColumns {
726b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
736b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        // This class cannot be instantiated
746b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        private MainTable() {}
756b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
766b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
776b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * The table name offered by this provider
786b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
796b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public static final String TABLE_NAME = "main";
806b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
816b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
826b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * The content:// style URL for this table
836b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
846b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public static final Uri CONTENT_URI =  Uri.parse("content://" + AUTHORITY + "/main");
856b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
866b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
876b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * The content URI base for a single row of data. Callers must
886b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * append a numeric row id to this Uri to retrieve a row
896b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
906b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public static final Uri CONTENT_ID_URI_BASE
916b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                = Uri.parse("content://" + AUTHORITY + "/main/");
926b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
936b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
946b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * The MIME type of {@link #CONTENT_URI}.
956b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
966b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public static final String CONTENT_TYPE
976b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                = "vnd.android.cursor.dir/vnd.example.api-demos-throttle";
986b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
996b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
1006b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * The MIME type of a {@link #CONTENT_URI} sub-directory of a single row.
1016b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
1026b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public static final String CONTENT_ITEM_TYPE
1036b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                = "vnd.android.cursor.item/vnd.example.api-demos-throttle";
1046b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
1056b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * The default sort order for this table
1066b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
1076b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public static final String DEFAULT_SORT_ORDER = "data COLLATE LOCALIZED ASC";
1086b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1096b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
1106b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * Column name for the single column holding our data.
1116b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * <P>Type: TEXT</P>
1126b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
1136b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public static final String COLUMN_NAME_DATA = "data";
1146b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    }
1156b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1166b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    /**
1176b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn     * This class helps open, create, and upgrade the database file.
1186b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn     */
1196b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn   static class DatabaseHelper extends SQLiteOpenHelper {
1206b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1216b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn       private static final String DATABASE_NAME = "loader_throttle.db";
1226b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn       private static final int DATABASE_VERSION = 2;
1236b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1246b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn       DatabaseHelper(Context context) {
1256b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1266b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn           // calls the super constructor, requesting the default cursor factory.
1276b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn           super(context, DATABASE_NAME, null, DATABASE_VERSION);
1286b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn       }
1296b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1306b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn       /**
1316b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        *
1326b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        * Creates the underlying database with table name and column names taken from the
1336b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        * NotePad class.
1346b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        */
1356b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn       @Override
1366b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn       public void onCreate(SQLiteDatabase db) {
1376b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn           db.execSQL("CREATE TABLE " + MainTable.TABLE_NAME + " ("
1386b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                   + MainTable._ID + " INTEGER PRIMARY KEY,"
1396b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                   + MainTable.COLUMN_NAME_DATA + " TEXT"
1406b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                   + ");");
1416b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn       }
1426b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1436b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn       /**
1446b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        *
1456b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        * Demonstrates that the provider must consider what happens when the
1466b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        * underlying datastore is changed. In this sample, the database is upgraded the database
1476b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        * by destroying the existing data.
1486b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        * A real application should upgrade the database in place.
1496b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        */
1506b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn       @Override
1516b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn       public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
1526b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1536b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn           // Logs that the database is being upgraded
1546b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn           Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
1556b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                   + newVersion + ", which will destroy all old data");
1566b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1576b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn           // Kills the table and existing data
1586b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn           db.execSQL("DROP TABLE IF EXISTS notes");
1596b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1606b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn           // Recreates the database with a new version
1616b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn           onCreate(db);
1626b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn       }
1636b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn   }
1646b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1656b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    /**
1666b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn     * A very simple implementation of a content provider.
1676b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn     */
1686b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    public static class SimpleProvider extends ContentProvider {
1696b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        // A projection map used to select columns from the database
1706b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        private final HashMap<String, String> mNotesProjectionMap;
1716b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        // Uri matcher to decode incoming URIs.
1726b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        private final UriMatcher mUriMatcher;
1736b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1746b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        // The incoming URI matches the main table URI pattern
1756b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        private static final int MAIN = 1;
1766b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        // The incoming URI matches the main table row ID URI pattern
1776b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        private static final int MAIN_ID = 2;
1786b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1796b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        // Handle to a new DatabaseHelper.
1806b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        private DatabaseHelper mOpenHelper;
1816b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1826b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
1836b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * Global provider initialization.
1846b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
1856b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public SimpleProvider() {
1866b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            // Create and initialize URI matcher.
1876b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
1886b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            mUriMatcher.addURI(AUTHORITY, MainTable.TABLE_NAME, MAIN);
1896b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            mUriMatcher.addURI(AUTHORITY, MainTable.TABLE_NAME + "/#", MAIN_ID);
1906b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1916b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            // Create and initialize projection map for all columns.  This is
1926b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            // simply an identity mapping.
1936b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            mNotesProjectionMap = new HashMap<String, String>();
1946b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            mNotesProjectionMap.put(MainTable._ID, MainTable._ID);
1956b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            mNotesProjectionMap.put(MainTable.COLUMN_NAME_DATA, MainTable.COLUMN_NAME_DATA);
1966b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
1976b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
1986b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
1996b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * Perform provider creation.
2006b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
2016b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        @Override
2026b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public boolean onCreate() {
2036b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            mOpenHelper = new DatabaseHelper(getContext());
2046b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            // Assumes that any failures will be reported by a thrown exception.
2056b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            return true;
2066b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
2076b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2086b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
2096b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * Handle incoming queries.
2106b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
2116b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        @Override
2126b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public Cursor query(Uri uri, String[] projection, String selection,
2136b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                String[] selectionArgs, String sortOrder) {
2146b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2156b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            // Constructs a new query builder and sets its table name
2166b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
2176b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            qb.setTables(MainTable.TABLE_NAME);
2186b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2196b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            switch (mUriMatcher.match(uri)) {
2206b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                case MAIN:
2216b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    // If the incoming URI is for main table.
2226b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    qb.setProjectionMap(mNotesProjectionMap);
2236b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    break;
2246b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2256b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                case MAIN_ID:
2266b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    // The incoming URI is for a single row.
2276b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    qb.setProjectionMap(mNotesProjectionMap);
2286b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    qb.appendWhere(MainTable._ID + "=?");
229a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganov                    selectionArgs = DatabaseUtilsCompat.appendSelectionArgs(selectionArgs,
2306b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                            new String[] { uri.getLastPathSegment() });
2316b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    break;
2326b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2336b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                default:
2346b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    throw new IllegalArgumentException("Unknown URI " + uri);
2356b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            }
2366b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2376b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2386b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            if (TextUtils.isEmpty(sortOrder)) {
2396b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                sortOrder = MainTable.DEFAULT_SORT_ORDER;
2406b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            }
2416b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2426b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            SQLiteDatabase db = mOpenHelper.getReadableDatabase();
2436b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2446b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            Cursor c = qb.query(db, projection, selection, selectionArgs,
2456b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    null /* no group */, null /* no filter */, sortOrder);
2466b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2476b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            c.setNotificationUri(getContext().getContentResolver(), uri);
2486b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            return c;
2496b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
2506b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2516b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
2526b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * Return the MIME type for an known URI in the provider.
2536b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
2546b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        @Override
2556b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public String getType(Uri uri) {
2566b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            switch (mUriMatcher.match(uri)) {
2576b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                case MAIN:
2586b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    return MainTable.CONTENT_TYPE;
2596b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                case MAIN_ID:
2606b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    return MainTable.CONTENT_ITEM_TYPE;
2616b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                default:
2626b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    throw new IllegalArgumentException("Unknown URI " + uri);
2636b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            }
2646b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
2656b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2666b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
2676b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * Handler inserting new data.
2686b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
2696b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        @Override
2706b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public Uri insert(Uri uri, ContentValues initialValues) {
2716b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            if (mUriMatcher.match(uri) != MAIN) {
2726b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                // Can only insert into to main URI.
2736b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                throw new IllegalArgumentException("Unknown URI " + uri);
2746b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            }
2756b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2766b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            ContentValues values;
2776b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2786b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            if (initialValues != null) {
2796b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                values = new ContentValues(initialValues);
2806b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            } else {
2816b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                values = new ContentValues();
2826b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            }
2836b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2846b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            if (values.containsKey(MainTable.COLUMN_NAME_DATA) == false) {
2856b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                values.put(MainTable.COLUMN_NAME_DATA, "");
2866b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            }
2876b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2886b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            SQLiteDatabase db = mOpenHelper.getWritableDatabase();
2896b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2906b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            long rowId = db.insert(MainTable.TABLE_NAME, null, values);
2916b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2926b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            // If the insert succeeded, the row ID exists.
2936b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            if (rowId > 0) {
2946b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                Uri noteUri = ContentUris.withAppendedId(MainTable.CONTENT_ID_URI_BASE, rowId);
2956b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                getContext().getContentResolver().notifyChange(noteUri, null);
2966b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                return noteUri;
2976b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            }
2986b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
2996b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            throw new SQLException("Failed to insert row into " + uri);
3006b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
3016b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3026b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
3036b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * Handle deleting data.
3046b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
3056b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        @Override
3066b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public int delete(Uri uri, String where, String[] whereArgs) {
3076b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            SQLiteDatabase db = mOpenHelper.getWritableDatabase();
3086b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            String finalWhere;
3096b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3106b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            int count;
3116b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3126b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            switch (mUriMatcher.match(uri)) {
3136b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                case MAIN:
3146b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    // If URI is main table, delete uses incoming where clause and args.
3156b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    count = db.delete(MainTable.TABLE_NAME, where, whereArgs);
3166b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    break;
3176b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3186b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    // If the incoming URI matches a single note ID, does the delete based on the
3196b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    // incoming data, but modifies the where clause to restrict it to the
3206b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    // particular note ID.
3216b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                case MAIN_ID:
3226b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    // If URI is for a particular row ID, delete is based on incoming
3236b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    // data but modified to restrict to the given ID.
324a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganov                    finalWhere = DatabaseUtilsCompat.concatenateWhere(
3256b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                            MainTable._ID + " = " + ContentUris.parseId(uri), where);
3266b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    count = db.delete(MainTable.TABLE_NAME, finalWhere, whereArgs);
3276b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    break;
3286b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3296b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                default:
3306b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    throw new IllegalArgumentException("Unknown URI " + uri);
3316b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            }
3326b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3336b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            getContext().getContentResolver().notifyChange(uri, null);
3346b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3356b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            return count;
3366b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
3376b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3386b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        /**
3396b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         * Handle updating data.
3406b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn         */
3416b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        @Override
3426b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
3436b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            SQLiteDatabase db = mOpenHelper.getWritableDatabase();
3446b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            int count;
3456b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            String finalWhere;
3466b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3476b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            switch (mUriMatcher.match(uri)) {
3486b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                case MAIN:
3496b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    // If URI is main table, update uses incoming where clause and args.
3506b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    count = db.update(MainTable.TABLE_NAME, values, where, whereArgs);
3516b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    break;
3526b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3536b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                case MAIN_ID:
3546b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    // If URI is for a particular row ID, update is based on incoming
3556b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    // data but modified to restrict to the given ID.
356a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganov                    finalWhere = DatabaseUtilsCompat.concatenateWhere(
3576b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                            MainTable._ID + " = " + ContentUris.parseId(uri), where);
3586b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    count = db.update(MainTable.TABLE_NAME, values, finalWhere, whereArgs);
3596b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    break;
3606b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3616b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                default:
3626b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    throw new IllegalArgumentException("Unknown URI " + uri);
3636b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            }
3646b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3656b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            getContext().getContentResolver().notifyChange(uri, null);
3666b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3676b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            return count;
3686b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
3696b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    }
3706b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3716b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    @Override
3726b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    protected void onCreate(Bundle savedInstanceState) {
3736b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        super.onCreate(savedInstanceState);
3746b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3756b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        FragmentManager fm = getSupportFragmentManager();
3766b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3776b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        // Create the list fragment and add it as our sole content.
3786b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        if (fm.findFragmentById(android.R.id.content) == null) {
3796b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            ThrottledLoaderListFragment list = new ThrottledLoaderListFragment();
3806b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            fm.beginTransaction().add(android.R.id.content, list).commit();
3816b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
3826b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    }
3836b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3846b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    public static class ThrottledLoaderListFragment extends ListFragment
3856b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            implements LoaderManager.LoaderCallbacks<Cursor> {
3866b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3876b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        // Menu identifiers
3886b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        static final int POPULATE_ID = Menu.FIRST;
3896b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        static final int CLEAR_ID = Menu.FIRST+1;
3906b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3916b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        // This is the Adapter being used to display the list's data.
3926b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        SimpleCursorAdapter mAdapter;
3936b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3946b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        // If non-null, this is the current filter the user has provided.
3956b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        String mCurFilter;
3966b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
3976b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        // Task we have running to populate the database.
3986b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        AsyncTask<Void, Void, Void> mPopulatingTask;
3996b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
4006b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        @Override public void onActivityCreated(Bundle savedInstanceState) {
4016b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            super.onActivityCreated(savedInstanceState);
4026b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
4036b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            setEmptyText("No data.  Select 'Populate' to fill with data from Z to A at a rate of 4 per second.");
4046b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            setHasOptionsMenu(true);
4056b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
4066b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            // Create an empty adapter we will use to display the loaded data.
4076b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            mAdapter = new SimpleCursorAdapter(getActivity(),
4086b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    android.R.layout.simple_list_item_1, null,
4096b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    new String[] { MainTable.COLUMN_NAME_DATA },
4106b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    new int[] { android.R.id.text1 }, 0);
4116b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            setListAdapter(mAdapter);
4126b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
413be6b6b494f094eea0abcd83eb8770bc4b9f7e34eDianne Hackborn            // Start out with a progress indicator.
414be6b6b494f094eea0abcd83eb8770bc4b9f7e34eDianne Hackborn            setListShown(false);
415be6b6b494f094eea0abcd83eb8770bc4b9f7e34eDianne Hackborn
4166b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            // Prepare the loader.  Either re-connect with an existing one,
4176b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            // or start a new one.
4186b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            getLoaderManager().initLoader(0, null, this);
4196b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
4206b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
4216b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
422a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganov            MenuItem populateItem = menu.add(Menu.NONE, POPULATE_ID, 0, "Populate");
423a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganov            MenuItemCompat.setShowAsAction(populateItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
424a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganov            MenuItem clearItem = menu.add(Menu.NONE, CLEAR_ID, 0, "Clear");
425a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganov            MenuItemCompat.setShowAsAction(clearItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
4266b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
4276b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
4286b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        @Override public boolean onOptionsItemSelected(MenuItem item) {
4296b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            final ContentResolver cr = getActivity().getContentResolver();
4306b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
4316b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            switch (item.getItemId()) {
4326b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                case POPULATE_ID:
4336b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    if (mPopulatingTask != null) {
4346b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                        mPopulatingTask.cancel(false);
4356b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    }
4366b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    mPopulatingTask = new AsyncTask<Void, Void, Void>() {
4376b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                        @Override protected Void doInBackground(Void... params) {
4386b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                            for (char c='Z'; c>='A'; c--) {
4396b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                if (isCancelled()) {
4406b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                    break;
4416b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                }
4426b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                StringBuilder builder = new StringBuilder("Data ");
4436b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                builder.append(c);
4446b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                ContentValues values = new ContentValues();
4456b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                values.put(MainTable.COLUMN_NAME_DATA, builder.toString());
4466b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                cr.insert(MainTable.CONTENT_URI, values);
4476b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                // Wait a bit between each insert.
4486b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                try {
4496b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                    Thread.sleep(250);
4506b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                } catch (InterruptedException e) {
4516b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                                }
4526b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                            }
4536b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                            return null;
4546b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                        }
4556b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    };
456a09e21a223dd1db2f3d16c1250f6607b712155dcSvetoslav Ganov                    mPopulatingTask.execute((Void[]) null);
4576b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    return true;
4586b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
4596b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                case CLEAR_ID:
4606b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    if (mPopulatingTask != null) {
4616b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                        mPopulatingTask.cancel(false);
4626b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                        mPopulatingTask = null;
4636b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    }
4646b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
4656b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                        @Override protected Void doInBackground(Void... params) {
4666b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                            cr.delete(MainTable.CONTENT_URI, null, null);
4676b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                            return null;
4686b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                        }
4696b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    };
4706b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    task.execute((Void[])null);
4716b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    return true;
4726b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
4736b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                default:
4746b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    return super.onOptionsItemSelected(item);
4756b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            }
4766b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
4776b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
4786b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        @Override public void onListItemClick(ListView l, View v, int position, long id) {
4796b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            // Insert desired behavior here.
4806b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            Log.i(TAG, "Item clicked: " + id);
4816b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
4826b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
4836b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        // These are the rows that we will retrieve.
4846b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        static final String[] PROJECTION = new String[] {
4856b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            MainTable._ID,
4866b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            MainTable.COLUMN_NAME_DATA,
4876b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        };
4886b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
4896b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
4906b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            CursorLoader cl = new CursorLoader(getActivity(), MainTable.CONTENT_URI,
4916b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn                    PROJECTION, null, null, null);
4926b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            cl.setUpdateThrottle(2000); // update at most every 2 seconds.
4936b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            return cl;
4946b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
4956b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
4966b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
4976b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            mAdapter.swapCursor(data);
498be6b6b494f094eea0abcd83eb8770bc4b9f7e34eDianne Hackborn
499be6b6b494f094eea0abcd83eb8770bc4b9f7e34eDianne Hackborn            // The list should now be shown.
500be6b6b494f094eea0abcd83eb8770bc4b9f7e34eDianne Hackborn            if (isResumed()) {
501be6b6b494f094eea0abcd83eb8770bc4b9f7e34eDianne Hackborn                setListShown(true);
502be6b6b494f094eea0abcd83eb8770bc4b9f7e34eDianne Hackborn            } else {
503be6b6b494f094eea0abcd83eb8770bc4b9f7e34eDianne Hackborn                setListShownNoAnimation(true);
504be6b6b494f094eea0abcd83eb8770bc4b9f7e34eDianne Hackborn            }
5056b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
5066b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn
5076b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        public void onLoaderReset(Loader<Cursor> loader) {
5086b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn            mAdapter.swapCursor(null);
5096b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn        }
5106b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn    }
5116b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn}
5126b3f9b3ac9327d22e73f4aa2b61e4fb6c3933a33Dianne Hackborn//END_INCLUDE(complete)
513