???????????????????????????????????????activity?????????fragment???棬???????????????????????????????????????????????μ??????????????????
??????????????????????????????????????????????????????anr????????????????????????????????handler???????????ui???檔??????????activity??
????fragment ??????????????????????? ????????????????????????????????? ?????? ??????????????????app??и??????????????????????????????μ????—Loader???????????????????????й?????????????
???????????????????????????? ????????????? ???????????????????????????ο????£?
????http://developer.android.com/intl/zh-cn/reference/android/app/LoaderManager.html
????http://developer.android.com/intl/zh-cn/reference/android/content/AsyncTaskLoader.html
????http://developer.android.com/intl/zh-cn/guide/components/loaders.html
??????????????????????????????????????
??????????????????????????????????????????????????????????£?????????????? ????????????????????????????? ???update ?????ui??
????package com.example.administrator.modifytestview;
????import android.app.Activity;
????import android.app.FragmentManager;
????import android.app.ListFragment;
????import android.app.LoaderManager;
????import android.content.CursorLoader;
????import android.content.Loader;
????import android.database.Cursor;
????import android.net.Uri;
????import android.os.Bundle;
????import android.provider.ContactsContract.Contacts;
????import android.util.Log;
????import android.view.View;
????import android.widget.ListView;
????import android.widget.SimpleCursorAdapter;
????public class MainActivity extends Activity {
????@Override
????protected void onCreate(Bundle savedInstanceState) {
????super.onCreate(savedInstanceState);
????setContentView(R.layout.activity_main);
????FragmentManager fm = getFragmentManager();
????CursorLoaderListFragment list = new CursorLoaderListFragment();
????fm.beginTransaction().replace(R.id.root?? list).commit();
????}
????public static class CursorLoaderListFragment extends ListFragment
????implements LoaderManager.LoaderCallbacks<Cursor> {
????// This is the Adapter being used to display the list's data.
????SimpleCursorAdapter mAdapter;
????// If non-null?? this is the current filter the user has provided.
????String mCurFilter;
????@Override
????public void onActivityCreated(Bundle savedInstanceState) {
????mAdapter = new SimpleCursorAdapter(getActivity()??
????android.R.layout.simple_list_item_2?? null??
????new String[]{Contacts.DISPLAY_NAME?? Contacts.CONTACT_STATUS}??
????new int[]{android.R.id.text1?? android.R.id.text2}?? 0);
????setListAdapter(mAdapter);
????//??????????????????loader
????getLoaderManager().initLoader(0?? null?? this);
????super.onActivityCreated(savedInstanceState);
????}
????@Override
????public void onListItemClick(ListView l?? View v?? int position?? long id) {
????// Insert desired behavior here.
????Log.i("FragmentComplexList"?? "Item clicked: " + id);
????}
????// These are the Contacts rows that we will retrieve.
????static final String[] CONTACTS_SUMMARY_PROJECTION = new String[]{
????Contacts._ID??
????Contacts.DISPLAY_NAME??
????Contacts.CONTACT_STATUS??
????Contacts.CONTACT_PRESENCE??
????Contacts.PHOTO_ID??
????Contacts.LOOKUP_KEY??
????};
????//?????????
????public Loader<Cursor> onCreateLoader(int id?? Bundle args) {
????// This is called when a new Loader needs to be created.  This
????// sample only has one Loader?? so we don't care about the ID.
????// First?? pick the base URI to use depending on whether we are
????// currently filtering.
????Uri baseUri;
????if (mCurFilter != null) {
????baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI??
????Uri.encode(mCurFilter));
????} else {
????baseUri = Contacts.CONTENT_URI;
????}
????// Now create and return a CursorLoader that will take care of
????// creating a Cursor for the data being displayed.
????String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
????+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
????+ Contacts.DISPLAY_NAME + " != '' ))";
????//????????????????????
????return new CursorLoader(getActivity()?? baseUri??
????CONTACTS_SUMMARY_PROJECTION?? select?? null??
????Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
????}
????//???????????и??μ????????????????????update ?????ui???
????public void onLoadFinished(Loader<Cursor> loader?? Cursor data) {
????// Swap the new cursor in.  (The framework will take care of closing the
????// old cursor once we return.)
????mAdapter.swapCursor(data);
????// The list should now be shown.
????if (isResumed()) {
????setListShown(true);
????} else {
????setListShownNoAnimation(true);
????}
????}
????public void onLoaderReset(Loader<Cursor> loader) {
????// This is called when the last Cursor provided to onLoadFinished()
????// above is about to be closed.  We need to make sure we are no
????// longer using it.
????mAdapter.swapCursor(null);
????}
????}
????}
?????????????????????????????????? ???loader????????Щ???裺
????1.??????activity??????fragment??????????????????? ??????????fragment??
????2.???LoaderManger??????????53?У?????get?????loadermanager??????????????????
????3.??????CursorLoader???????contentProvider??????????90-97?? ??????????
????4.?????????LoaderCallBack?????????????????????????? д???????????????? ???ɡ???34?????е????
????????3????????????????????????????????????????
?????????????????·??????????????????? ??????????????????e???????contentprovider???????app???????????????????????????????????????????????????????????????????????????????????????????add???????????????????????????????????????и?listview ?????????? ??????????仯?????????????б??
?????????????? ???????demo???? CursorLoader?????????????
????public class CursorLoader extends AsyncTaskLoader<Cursor> {
???????????????????????contentProvider??Loader ??????AsyncTaskLoader?????
??????????????????
????package com.example.administrator.activeandroidtest3;
????import android.content.AsyncTaskLoader;
????import android.content.Context;
????import android.database.Cursor;
????public abstract class SimpleCursorLoader extends AsyncTaskLoader<Cursor> {
????private Cursor mCursor;
????public SimpleCursorLoader(Context context) {
????super(context);
????}
????/* ????????????? */
????@Override
????public abstract Cursor loadInBackground();
????/* ??ui ????????? */
????@Override
????public void deliverResult(Cursor cursor) {
????if (isReset()) {
????// An async query came in while the loader is stopped
????if (cursor != null) {
????cursor.close();
????}
????return;
????}
????Cursor oldCursor = mCursor;
????mCursor = cursor;
????if (isStarted()) {
????super.deliverResult(cursor);
????}
????if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
????oldCursor.close();
????}
????}
????@Override
????protected void onStartLoading() {
????if (mCursor != null) {
????deliverResult(mCursor);
????}
????if (takeContentChanged() || mCursor == null) {
????forceLoad();
????}
????}
????@Override
????protected void onStopLoading() {
????cancelLoad();
????}
????@Override
????public void onCanceled(Cursor cursor) {
????if (cursor != null && !cursor.isClosed()) {
????cursor.close();
????}
????}
????@Override
????protected void onReset() {
????super.onReset();
????onStopLoading();
????if (mCursor != null && !mCursor.isClosed()) {
????mCursor.close();
????}
????mCursor = null;
????}
????}
?????????????????????????? ?????provider??loader?????(??????????д??????????? cursor????ó????????????????????д??private????????????????? ?????????????)??
????package com.example.administrator.activeandroidtest3;
????import android.content.Context;
????import android.database.Cursor;
????import android.database.sqlite.SQLiteDatabase;
????/**
????* Created by Administrator on 2015/10/7.
????*/
????public class SpecialLoader extends SimpleCursorLoader {
????ForceLoadContentObserver mObserver = new ForceLoadContentObserver();
????private Context context;
????public SpecialLoader(Context context) {
????super(context);
????this.context = context;
????}
????@Override
????public Cursor loadInBackground() {
????DatabaseHelper dh = new DatabaseHelper(context?? "Test.db");
????SQLiteDatabase database = dh.getReadableDatabase();
????String table = "Student";
????String[] columns = new String[]{"Name"?? "No"};
????//????????????????activeandroid ??orm ????????????????????????Id??????SimpleCursorAdapter
????//???????_id ??????????????????????????
????Cursor cursor = database.rawQuery("SELECT Id AS _id??Name??No FROM Student"?? null);
????if (database != null) {
????if (cursor != null) {
????//??????????????
????cursor.registerContentObserver(mObserver);
????//???????? ???????????uri??仯??????????????uri??ж????provider???
????//??????????????????? ????????uri
????cursor.setNotificationUri(context.getContentResolver()?? MainActivity.uri);
????}
????}
????return cursor;
????}
????}
??????????????????activity ??????????
????package com.example.administrator.activeandroidtest3;
????import android.app.Activity;
????import android.app.LoaderManager;
????import android.content.Loader;
????import android.database.Cursor;
????import android.net.Uri;
????import android.os.Bundle;
????import android.util.Log;
????import android.view.Menu;
????import android.view.MenuItem;
????import android.view.View;
????import android.widget.ListView;
????import android.widget.SimpleCursorAdapter;
????import android.widget.TextView;
????import com.activeandroid.query.Select;
????import java.util.List;
????import java.util.Random;
????public class MainActivity extends Activity implements LoaderManager.LoaderCallbacks {
????public static final Uri uri = Uri.parse("content://com.example.student");
????private TextView addTv;
????private ListView lv;
????private SimpleCursorAdapter adapter;
????@Override
????protected void onCreate(Bundle savedInstanceState) {
????super.onCreate(savedInstanceState);
????setContentView(R.layout.activity_main);
????addTv = (TextView) this.findViewById(R.id.add);
????addTv.setOnClickListener(new View.OnClickListener() {
????@Override
????public void onClick(View v) {
????Student student = new Student();
????student.name = getRandomString(5);
????student.no = (int) (Math.random() * 1000) + "";
????student.sex = (int) (Math.random() * 1);
????student.save();
????//????????????notify ???loader?????????
????getContentResolver().notifyChange(uri?? null);
????}
????});
????lv = (ListView) this.findViewById(R.id.lv);
????adapter = new SimpleCursorAdapter(MainActivity.this??
????android.R.layout.simple_list_item_2?? null??
????new String[]{"Name"?? "No"}??
????new int[]{android.R.id.text1?? android.R.id.text2}?? 0);
????lv.setAdapter(adapter);
????getLoaderManager().initLoader(0?? null?? this);
????}
????@Override
????public boolean onCreateOptionsMenu(Menu menu) {
????// Inflate the menu; this adds items to the action bar if it is present.
????getMenuInflater().inflate(R.menu.menu_main?? menu);
????return true;
????}
????@Override
????public boolean onOptionsItemSelected(MenuItem item) {
????// Handle action bar item clicks here. The action bar will
????// automatically handle clicks on the Home/Up button?? so long
????// as you specify a parent activity in AndroidManifest.xml.
????int id = item.getItemId();
????//noinspection SimplifiableIfStatement
????if (id == R.id.action_settings) {
????return true;
????}
????return super.onOptionsItemSelected(item);
????}
????public static String getRandomString(int length) { //length?????????????????
????String base = "abcdefghijklmnopqrstuvwxyz0123456789";
????Random random = new Random();
????StringBuffer sb = new StringBuffer();
????for (int i = 0; i < length; i++) {
????int number = random.nextInt(base.length());
????sb.append(base.charAt(number));
????}
????return sb.toString();
????}
????@Override
????public Loader onCreateLoader(int id?? Bundle args) {
????SpecialLoader loader = new SpecialLoader(MainActivity.this);
????return loader;
????}
????@Override
????public void onLoadFinished(Loader loader?? Object data) {
????adapter.swapCursor((Cursor) data);
????}
????@Override
????public void onLoaderReset(Loader loader) {
????}
????}
????????????????е?Ч????

?????????????? ????????????????????? ????????????provider????db?????????????? ???????£????????????????????????????????????????????????????????????????????
????http://developer.android.com/intl/zh-cn/reference/android/content/AsyncTaskLoader.html