android 1.6下使用 Loader示例

android 3.0 sdk,引入了不少新api,好比Loader。和Fragment相似(編寫兼容android1.6的fragment),該api也可在android 1.6以上版本執行。android

如下介紹如何編寫Loader,實現對ListView的異步加載。效果如圖:sql

imageimage

示例中有一個後臺線程每隔3秒更新數據庫的長江記錄,將記錄改成「長江」或「Long River」。ListView無需監控數據庫變化,基於Loader,會自動更新。實際上這裏面是觀察者模式,無非是系統自帶了,只需調用便可,無需本身構造觀察者。數據庫

這個示例也是完整的sqlite+content provider+cursor adapter+listview+loader組合示例。api

編寫前的準備相似編寫兼容android1.6的fragment,須要導入jar包。異步

另外,2.3之前的Activity類沒有提供一些Loader的幫助方法,須要讓本身的Activity實現類繼承FragmentActivity:ide

public class ListViewActivity extends FragmentActivitysvn

本示例是在在視圖顯示中使用Theme基礎上實現的。this

Activity類和RiverContentProvider類作了修改。google

Activity類:線程

public class ListViewActivity extends FragmentActivity {

    private ListView riverListView;

    private SimpleCursorAdapter adapter;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        initLoader();
        setRiverListViewAdapter();
    }

    private void initLoader() {
        getSupportLoaderManager().initLoader(0, null,
                new LoaderCallbacks<Cursor>() {

                    @Override
                    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
                        Log.d("list", "on create loader");
                         CursorLoader cursorLoader=new CursorLoader(ListViewActivity.this,
                                RiverContentProvider.CONTENT_URI, new String[] {
                                        RiverContentProvider._ID,
                                        RiverContentProvider.NAME,
                                        RiverContentProvider.INTRODUCTION },
                                null, null, null);
                         //cursorLoader.setUpdateThrottle(1000);
                         return cursorLoader;
                    }

                    @Override
                    public void onLoadFinished(Loader<Cursor> loader,
                            Cursor cursor) {
                        Log.d("list", "on loader finished");
                        adapter.swapCursor(cursor);
                    }

                    @Override
                    public void onLoaderReset(Loader<Cursor> loader) {
                        Log.d("list", "on loader reset");
                        adapter.swapCursor(null);
                    }
                });
    }

    private void setRiverListViewAdapter() {
        riverListView = (ListView) this.findViewById(R.id.riverList);

        Cursor cursor = managedQuery(RiverContentProvider.CONTENT_URI, null,
                null, null, null);
        adapter = new SimpleCursorAdapter(this, R.layout.row, cursor,
                new String[] { RiverContentProvider.NAME,
                        RiverContentProvider.INTRODUCTION }, new int[] {
                        R.id.riverName, R.id.riverIntroduction }, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        riverListView.setAdapter(adapter);
    }

 

主要是增長了initLoader方法。這裏主要是實現了LoaderCallbacks接口。其中:

  • onCreateLoader,在建立activity時跟着onCreate會調用一次
  • onLoadFinished,每次改變和Loader相關的數據庫記錄後會調用一次
  • onLoaderReset,在關閉Activity時調用,釋放資源

而後,在Content provider中,要調用相似觀察者模式中通知的方法,即,在update方法中通知觀察者記錄改變,在query方法中註冊觀察者,這樣通知來了可接收並處理。

update方法:

@Override
public int update(Uri uri, ContentValues values, String selection,
        String[] selectionArgs) {
    int returnValue = database.update("rivers", values, selection,
            selectionArgs);
   getContext().getContentResolver().notifyChange(uri, null);
    return returnValue;
}

query方法:

public Cursor query(Uri uri, String[] projection, String selection,
        String[] selectionArgs, String sortOrder) {
    Cursor cursor = database.query("rivers", projection, selection,
            selectionArgs, null, null, sortOrder);
   cursor.setNotificationUri(getContext().getContentResolver(), uri);
    return cursor;
}

這裏要注意,這個觀察者模式是從sdk level 1就有的,也就是說,cursor能夠接收通知來感知content provider數據變化,可是不能作到異步刷新界面。此次Loader機制經過官方支持實現了這個功能。

另外,經過本示例也可觀察到,當關閉Activity後,Content provider繼續工做,它的後臺線程還在不停的更新記錄。

源代碼見:

http://easymorse.googlecode.com/svn/tags/CustomListViewDemo-0.4/

相關文章
相關標籤/搜索