• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

development


Commit MetaInfo

Revisãob3464311899462843c4d9bf69079ed0d8879b73d (tree)
Hora2011-01-09 10:36:45
AutorDianne Hackborn <hackbod@goog...>
CommiterAndroid Git Automerger

Mensagem de Log

am ddfb4b38: Merge "Clean up to no longer use old APIs, add new loader throttle sample." into honeycomb

* commit 'ddfb4b38f5935fe19b08597926aa90eb2ce6c43c':

Clean up to no longer use old APIs, add new loader throttle sample.

Mudança Sumário

Diff

--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -342,6 +342,18 @@
342342 </intent-filter>
343343 </activity>
344344
345+ <!-- Loader Samples -->
346+
347+ <activity android:name=".app.LoaderThrottle"
348+ android:label="@string/loader_throttle">
349+ <intent-filter>
350+ <action android:name="android.intent.action.MAIN" />
351+ <category android:name="android.intent.category.SAMPLE_CODE" />
352+ </intent-filter>
353+ </activity>
354+ <provider android:name=".app.LoaderThrottle$SimpleProvider"
355+ android:authorities="com.example.android.apis.app.LoaderThrottle" />
356+
345357 <!-- Intent Samples -->
346358
347359 <activity android:name=".app.Intents" android:label="@string/activity_intents">
--- a/samples/ApiDemos/res/values/strings.xml
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -146,6 +146,8 @@
146146 <string name="fragment_stack">App/Fragment/Stack</string>
147147 <string name="new_fragment">New fragment</string>
148148
149+ <string name="loader_throttle">App/Loader/Throttle</string>
150+
149151 <string name="activity_menu">App/Activity/Menu</string>
150152 <string name="open_menu">Open menu</string>
151153 <string name="close_menu">Close menu</string>
--- a/samples/ApiDemos/src/com/example/android/apis/app/FragmentListCursorLoader.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentListCursorLoader.java
@@ -16,12 +16,10 @@
1616
1717 package com.example.android.apis.app;
1818
19-import com.example.android.apis.R;
20-
2119 import android.app.Activity;
20+import android.app.FragmentManager;
2221 import android.app.ListFragment;
2322 import android.app.LoaderManager;
24-import android.content.Context;
2523 import android.content.CursorLoader;
2624 import android.content.Loader;
2725 import android.database.Cursor;
@@ -34,7 +32,6 @@ import android.view.Menu;
3432 import android.view.MenuInflater;
3533 import android.view.MenuItem;
3634 import android.view.View;
37-import android.view.inputmethod.InputMethodManager;
3835 import android.widget.ListView;
3936 import android.widget.SearchView;
4037 import android.widget.SimpleCursorAdapter;
@@ -50,10 +47,12 @@ public class FragmentListCursorLoader extends Activity {
5047 protected void onCreate(Bundle savedInstanceState) {
5148 super.onCreate(savedInstanceState);
5249
50+ FragmentManager fm = getFragmentManager();
51+
5352 // Create the list fragment and add it as our sole content.
54- if (findFragmentById(android.R.id.content) == null) {
53+ if (fm.findFragmentById(android.R.id.content) == null) {
5554 CursorLoaderListFragment list = new CursorLoaderListFragment();
56- openFragmentTransaction().add(android.R.id.content, list).commit();
55+ fm.openTransaction().add(android.R.id.content, list).commit();
5756 }
5857 }
5958
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.java
@@ -0,0 +1,514 @@
1+/*
2+ * Copyright (C) 2010 The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+package com.example.android.apis.app;
18+
19+import android.app.Activity;
20+import android.app.FragmentManager;
21+import android.app.ListFragment;
22+import android.app.LoaderManager;
23+import android.content.ContentProvider;
24+import android.content.ContentResolver;
25+import android.content.ContentUris;
26+import android.content.ContentValues;
27+import android.content.Context;
28+import android.content.CursorLoader;
29+import android.content.Loader;
30+import android.content.UriMatcher;
31+import android.database.Cursor;
32+import android.database.SQLException;
33+import android.database.sqlite.SQLiteDatabase;
34+import android.database.sqlite.SQLiteOpenHelper;
35+import android.database.sqlite.SQLiteQueryBuilder;
36+import android.net.Uri;
37+import android.os.AsyncTask;
38+import android.os.Bundle;
39+import android.provider.BaseColumns;
40+import android.text.TextUtils;
41+import android.util.Log;
42+import android.view.Menu;
43+import android.view.MenuInflater;
44+import android.view.MenuItem;
45+import android.view.View;
46+import android.widget.ListView;
47+import android.widget.SimpleCursorAdapter;
48+
49+import java.util.HashMap;
50+
51+/**
52+ * Demonstration of bottom to top implementation of a content provider holding
53+ * structured data through displaying it in the UI, using throttling to reduce
54+ * the number of queries done when its data changes.
55+ */
56+public class LoaderThrottle extends Activity {
57+ // Debugging.
58+ static final String TAG = "LoaderThrottle";
59+
60+ /**
61+ * The authority we use to get to our sample provider.
62+ */
63+ public static final String AUTHORITY = "com.example.android.apis.app.LoaderThrottle";
64+
65+ /**
66+ * Definition of the contract for the main table of our provider.
67+ */
68+ public static final class MainTable implements BaseColumns {
69+
70+ // This class cannot be instantiated
71+ private MainTable() {}
72+
73+ /**
74+ * The table name offered by this provider
75+ */
76+ public static final String TABLE_NAME = "main";
77+
78+ /**
79+ * The content:// style URL for this table
80+ */
81+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/main");
82+
83+ /**
84+ * The content URI base for a single row of data. Callers must
85+ * append a numeric row id to this Uri to retrieve a row
86+ */
87+ public static final Uri CONTENT_ID_URI_BASE
88+ = Uri.parse("content://" + AUTHORITY + "/main/");
89+
90+ /**
91+ * 0-relative position of a main ID segment in the path part of a main ID URI
92+ */
93+ public static final int MAIN_ID_PATH_POSITION = 1;
94+
95+ /**
96+ * The MIME type of {@link #CONTENT_URI}.
97+ */
98+ public static final String CONTENT_TYPE
99+ = "vnd.android.cursor.dir/vnd.example.api-demos-throttle";
100+
101+ /**
102+ * The MIME type of a {@link #CONTENT_URI} sub-directory of a single row.
103+ */
104+ public static final String CONTENT_ITEM_TYPE
105+ = "vnd.android.cursor.item/vnd.example.api-demos-throttle";
106+ /**
107+ * The default sort order for this table
108+ */
109+ public static final String DEFAULT_SORT_ORDER = "data COLLATE LOCALIZED ASC";
110+
111+ /**
112+ * Column name for the single column holding our data.
113+ * <P>Type: TEXT</P>
114+ */
115+ public static final String COLUMN_NAME_DATA = "data";
116+ }
117+
118+ /**
119+ * This class helps open, create, and upgrade the database file.
120+ */
121+ static class DatabaseHelper extends SQLiteOpenHelper {
122+
123+ private static final String DATABASE_NAME = "loader_throttle.db";
124+ private static final int DATABASE_VERSION = 2;
125+
126+ DatabaseHelper(Context context) {
127+
128+ // calls the super constructor, requesting the default cursor factory.
129+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
130+ }
131+
132+ /**
133+ *
134+ * Creates the underlying database with table name and column names taken from the
135+ * NotePad class.
136+ */
137+ @Override
138+ public void onCreate(SQLiteDatabase db) {
139+ db.execSQL("CREATE TABLE " + MainTable.TABLE_NAME + " ("
140+ + MainTable._ID + " INTEGER PRIMARY KEY,"
141+ + MainTable.COLUMN_NAME_DATA + " TEXT"
142+ + ");");
143+ }
144+
145+ /**
146+ *
147+ * Demonstrates that the provider must consider what happens when the
148+ * underlying datastore is changed. In this sample, the database is upgraded the database
149+ * by destroying the existing data.
150+ * A real application should upgrade the database in place.
151+ */
152+ @Override
153+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
154+
155+ // Logs that the database is being upgraded
156+ Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
157+ + newVersion + ", which will destroy all old data");
158+
159+ // Kills the table and existing data
160+ db.execSQL("DROP TABLE IF EXISTS notes");
161+
162+ // Recreates the database with a new version
163+ onCreate(db);
164+ }
165+ }
166+
167+ /**
168+ * A very simple implementation of a content provider.
169+ */
170+ public static class SimpleProvider extends ContentProvider {
171+ // A projection map used to select columns from the database
172+ private final HashMap<String, String> mNotesProjectionMap;
173+ // Uri matcher to decode incoming URIs.
174+ private final UriMatcher mUriMatcher;
175+
176+ // The incoming URI matches the main table URI pattern
177+ private static final int MAIN = 1;
178+ // The incoming URI matches the main table row ID URI pattern
179+ private static final int MAIN_ID = 2;
180+
181+ // Handle to a new DatabaseHelper.
182+ private DatabaseHelper mOpenHelper;
183+
184+ /**
185+ * Global provider initialization.
186+ */
187+ public SimpleProvider() {
188+ // Create and initialize URI matcher.
189+ mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
190+ mUriMatcher.addURI(AUTHORITY, MainTable.TABLE_NAME, MAIN);
191+ mUriMatcher.addURI(AUTHORITY, MainTable.TABLE_NAME + "/#", MAIN_ID);
192+
193+ // Create and initialize projection map for all columns. This is
194+ // simply an identity mapping.
195+ mNotesProjectionMap = new HashMap<String, String>();
196+ mNotesProjectionMap.put(MainTable._ID, MainTable._ID);
197+ mNotesProjectionMap.put(MainTable.COLUMN_NAME_DATA, MainTable.COLUMN_NAME_DATA);
198+ }
199+
200+ /**
201+ * Perform provider creation.
202+ */
203+ @Override
204+ public boolean onCreate() {
205+ mOpenHelper = new DatabaseHelper(getContext());
206+ // Assumes that any failures will be reported by a thrown exception.
207+ return true;
208+ }
209+
210+ /**
211+ * Handle incoming queries.
212+ */
213+ @Override
214+ public Cursor query(Uri uri, String[] projection, String selection,
215+ String[] selectionArgs, String sortOrder) {
216+
217+ // Constructs a new query builder and sets its table name
218+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
219+ qb.setTables(MainTable.TABLE_NAME);
220+
221+ switch (mUriMatcher.match(uri)) {
222+ case MAIN:
223+ // If the incoming URI is for main table.
224+ qb.setProjectionMap(mNotesProjectionMap);
225+ break;
226+
227+ case MAIN_ID:
228+ // The incoming URI is for a single row.
229+ qb.setProjectionMap(mNotesProjectionMap);
230+ qb.appendWhere(MainTable._ID + "=" + uri.getPathSegments().get(
231+ MainTable.MAIN_ID_PATH_POSITION));
232+ break;
233+
234+ default:
235+ throw new IllegalArgumentException("Unknown URI " + uri);
236+ }
237+
238+
239+ if (TextUtils.isEmpty(sortOrder)) {
240+ sortOrder = MainTable.DEFAULT_SORT_ORDER;
241+ }
242+
243+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
244+
245+ Cursor c = qb.query(db, projection, selection, selectionArgs,
246+ null /* no group */, null /* no filter */, sortOrder);
247+
248+ c.setNotificationUri(getContext().getContentResolver(), uri);
249+ return c;
250+ }
251+
252+ /**
253+ * Return the MIME type for an known URI in the provider.
254+ */
255+ @Override
256+ public String getType(Uri uri) {
257+ switch (mUriMatcher.match(uri)) {
258+ case MAIN:
259+ return MainTable.CONTENT_TYPE;
260+ case MAIN_ID:
261+ return MainTable.CONTENT_ITEM_TYPE;
262+ default:
263+ throw new IllegalArgumentException("Unknown URI " + uri);
264+ }
265+ }
266+
267+ /**
268+ * Handler inserting new data.
269+ */
270+ @Override
271+ public Uri insert(Uri uri, ContentValues initialValues) {
272+ if (mUriMatcher.match(uri) != MAIN) {
273+ // Can only insert into to main URI.
274+ throw new IllegalArgumentException("Unknown URI " + uri);
275+ }
276+
277+ ContentValues values;
278+
279+ if (initialValues != null) {
280+ values = new ContentValues(initialValues);
281+ } else {
282+ values = new ContentValues();
283+ }
284+
285+ if (values.containsKey(MainTable.COLUMN_NAME_DATA) == false) {
286+ values.put(MainTable.COLUMN_NAME_DATA, "");
287+ }
288+
289+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
290+
291+ long rowId = db.insert(MainTable.TABLE_NAME, null, values);
292+
293+ // If the insert succeeded, the row ID exists.
294+ if (rowId > 0) {
295+ Uri noteUri = ContentUris.withAppendedId(MainTable.CONTENT_ID_URI_BASE, rowId);
296+ getContext().getContentResolver().notifyChange(noteUri, null);
297+ return noteUri;
298+ }
299+
300+ throw new SQLException("Failed to insert row into " + uri);
301+ }
302+
303+ /**
304+ * Handle deleting data.
305+ */
306+ @Override
307+ public int delete(Uri uri, String where, String[] whereArgs) {
308+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
309+ String finalWhere;
310+
311+ int count;
312+
313+ switch (mUriMatcher.match(uri)) {
314+ case MAIN:
315+ // If URI is main table, delete uses incoming where clause and args.
316+ count = db.delete(MainTable.TABLE_NAME, where, whereArgs);
317+ break;
318+
319+ // If the incoming URI matches a single note ID, does the delete based on the
320+ // incoming data, but modifies the where clause to restrict it to the
321+ // particular note ID.
322+ case MAIN_ID:
323+ // If URI is for a particular row ID, delete is based on incoming
324+ // data but modified to restrict to the given ID.
325+ finalWhere = MainTable._ID + " = " + uri.getPathSegments().get(
326+ MainTable.MAIN_ID_PATH_POSITION);
327+
328+ if (where != null) {
329+ // Combine with incoming where, if specified.
330+ finalWhere = finalWhere + " AND " + where;
331+ }
332+
333+ count = db.delete(MainTable.TABLE_NAME, finalWhere, whereArgs);
334+ break;
335+
336+ default:
337+ throw new IllegalArgumentException("Unknown URI " + uri);
338+ }
339+
340+ getContext().getContentResolver().notifyChange(uri, null);
341+
342+ return count;
343+ }
344+
345+ /**
346+ * Handle updating data.
347+ */
348+ @Override
349+ public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
350+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
351+ int count;
352+ String finalWhere;
353+
354+ switch (mUriMatcher.match(uri)) {
355+ case MAIN:
356+ // If URI is main table, update uses incoming where clause and args.
357+ count = db.update(MainTable.TABLE_NAME, values, where, whereArgs);
358+ break;
359+
360+ case MAIN_ID:
361+ // If URI is for a particular row ID, update is based on incoming
362+ // data but modified to restrict to the given ID.
363+ finalWhere = MainTable._ID + " = " + uri.getPathSegments().get(
364+ MainTable.MAIN_ID_PATH_POSITION);
365+
366+ if (where != null) {
367+ // Combine with incoming where, if specified.
368+ finalWhere = finalWhere + " AND " + where;
369+ }
370+
371+ count = db.update(MainTable.TABLE_NAME, values, finalWhere, whereArgs);
372+ break;
373+
374+ default:
375+ throw new IllegalArgumentException("Unknown URI " + uri);
376+ }
377+
378+ getContext().getContentResolver().notifyChange(uri, null);
379+
380+ return count;
381+ }
382+ }
383+
384+ @Override
385+ protected void onCreate(Bundle savedInstanceState) {
386+ super.onCreate(savedInstanceState);
387+
388+ FragmentManager fm = getFragmentManager();
389+
390+ // Create the list fragment and add it as our sole content.
391+ if (fm.findFragmentById(android.R.id.content) == null) {
392+ ThrottledLoaderListFragment list = new ThrottledLoaderListFragment();
393+ fm.openTransaction().add(android.R.id.content, list).commit();
394+ }
395+ }
396+
397+ public static class ThrottledLoaderListFragment extends ListFragment
398+ implements LoaderManager.LoaderCallbacks<Cursor> {
399+
400+ // Menu identifiers
401+ static final int POPULATE_ID = Menu.FIRST;
402+ static final int CLEAR_ID = Menu.FIRST+1;
403+
404+ // This is the Adapter being used to display the list's data.
405+ SimpleCursorAdapter mAdapter;
406+
407+ // If non-null, this is the current filter the user has provided.
408+ String mCurFilter;
409+
410+ // Task we have running to populate the database.
411+ AsyncTask<Void, Void, Void> mPopulatingTask;
412+
413+ @Override public void onActivityCreated(Bundle savedInstanceState) {
414+ super.onActivityCreated(savedInstanceState);
415+
416+ setEmptyText("No data");
417+ setHasOptionsMenu(true);
418+
419+ // Create an empty adapter we will use to display the loaded data.
420+ mAdapter = new SimpleCursorAdapter(getActivity(),
421+ android.R.layout.simple_list_item_1, null,
422+ new String[] { MainTable.COLUMN_NAME_DATA },
423+ new int[] { android.R.id.text1 }, 0);
424+ setListAdapter(mAdapter);
425+
426+ // Prepare the loader. Either re-connect with an existing one,
427+ // or start a new one.
428+ getLoaderManager().initLoader(0, null, this);
429+ }
430+
431+ @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
432+ menu.add(Menu.NONE, POPULATE_ID, 0, "Populate")
433+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
434+ menu.add(Menu.NONE, CLEAR_ID, 0, "Clear")
435+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
436+ }
437+
438+ @Override public boolean onOptionsItemSelected(MenuItem item) {
439+ final ContentResolver cr = getActivity().getContentResolver();
440+
441+ switch (item.getItemId()) {
442+ case POPULATE_ID:
443+ if (mPopulatingTask != null) {
444+ mPopulatingTask.cancel(false);
445+ }
446+ mPopulatingTask = new AsyncTask<Void, Void, Void>() {
447+ @Override protected Void doInBackground(Void... params) {
448+ for (char c='Z'; c>='A'; c--) {
449+ if (isCancelled()) {
450+ break;
451+ }
452+ StringBuilder builder = new StringBuilder("Data ");
453+ builder.append(c);
454+ ContentValues values = new ContentValues();
455+ values.put(MainTable.COLUMN_NAME_DATA, builder.toString());
456+ cr.insert(MainTable.CONTENT_URI, values);
457+ // Wait a bit between each insert.
458+ try {
459+ Thread.sleep(250);
460+ } catch (InterruptedException e) {
461+ }
462+ }
463+ return null;
464+ }
465+ };
466+ mPopulatingTask.execute((Void[])null);
467+ return true;
468+
469+ case CLEAR_ID:
470+ if (mPopulatingTask != null) {
471+ mPopulatingTask.cancel(false);
472+ mPopulatingTask = null;
473+ }
474+ AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
475+ @Override protected Void doInBackground(Void... params) {
476+ cr.delete(MainTable.CONTENT_URI, null, null);
477+ return null;
478+ }
479+ };
480+ task.execute((Void[])null);
481+ return true;
482+
483+ default:
484+ return super.onOptionsItemSelected(item);
485+ }
486+ }
487+
488+ @Override public void onListItemClick(ListView l, View v, int position, long id) {
489+ // Insert desired behavior here.
490+ Log.i(TAG, "Item clicked: " + id);
491+ }
492+
493+ // These are the rows that we will retrieve.
494+ static final String[] PROJECTION = new String[] {
495+ MainTable._ID,
496+ MainTable.COLUMN_NAME_DATA,
497+ };
498+
499+ @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) {
500+ CursorLoader cl = new CursorLoader(getActivity(), MainTable.CONTENT_URI,
501+ PROJECTION, null, null, null);
502+ //cl.setUpdateThrottle(2000); // update at most every 2 seconds.
503+ return cl;
504+ }
505+
506+ @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
507+ mAdapter.swapCursor(data);
508+ }
509+
510+ @Override public void onLoaderReset(Loader<Cursor> loader) {
511+ mAdapter.swapCursor(null);
512+ }
513+ }
514+}
--- a/samples/ApiDemos/src/com/example/android/apis/app/_index.html
+++ b/samples/ApiDemos/src/com/example/android/apis/app/_index.html
@@ -122,6 +122,16 @@
122122
123123 </dl>
124124
125+<h3>LoaderManager</h3>
126+<dl>
127+ <dt><a href="LoaderThrottle.html">Loader Throttle</a></dt>
128+ <dd>Complete end-to-end demonstration of a simple content provider that
129+ populates data in a list through a cursor loader. The UI allows the list
130+ to be populated with a series of items, showing how AsyncTaskLoader's
131+ throttling facility can be used to control how much a Loader is refreshed
132+ in this case.</dd>
133+</dl>
134+
125135 <h3>Service</h3>
126136 <dl>
127137 <dt><a href="LocalService.html">Local Service</a></dt>