1. 程式人生 > >使用AsyncTaskLoader動態載入SQLite資料

使用AsyncTaskLoader動態載入SQLite資料

Andorid API Guides中有一章節ListView講解了如何使用CursorLoader動態載入資料。但CursorLoader只支援Content Provider,實際上在很多小應用中都用不到Content Provider。我嘗試繼承CursorLoader的父類也就是AsyncTaskLoader實現了一個簡單的動態載入SQLite資料的方案。如有不當之處希望指正。


NotesLoader繼承AsyncTaskLoader

public class NotesLoader extends AsyncTaskLoader<Cursor> {
    private NotesDbAdapter notesDbAdapter;	//NotesDBAdapter可以在Android Example中找到,這裡略作修改,以便支援多資料表的訪問

    public NotesLoader(Context context, String tableName) {
        super(context);
        notesDbAdapter = new NotesDbAdapter(context, tableName);
    }

    @Override
    protected void onStartLoading() {
        Log.v("onStartLoading", "OK");
        forceLoad();	//強制載入
    }
    @Override
    public Cursor loadInBackground() {
        Log.v("loadInBackground","OK");
        notesDbAdapter.open();
        mCursor = notesDbAdapter.fetchAllNotes();
        return mCursor;
    }

    @Override
    protected void onStopLoading() {
        Log.v("onStopLoading","OK");
        notesDbAdapter.close();
    }
}

PlaceholderFragment介面LoaderManager,換成Activity也是一樣的

public class PlaceholderFragment extends ListFragment
        implements LoaderManager.LoaderCallbacks<Cursor>{
    private Cursor mNotesCursor;
    private SimpleCursorAdapter notesAdapter=null;
    private int oldLoaderId;
    private int newLoaderId;

    public PlaceholderFragment() {    }

    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);

        // Create an array to specify the fields we want to display in the list (only TITLE)
        String[] from = new String[]{NotesDbAdapter.KEY_TITLE};

        // and an array of the fields we want to bind those fields to (in this case just text1)
        int[] to = new int[]{R.id.subject_date_text1};
        notesAdapter =
                new SimpleCursorAdapter(getActivity(), R.layout.row_subject_date, null, from, to, 0);
        setListAdapter(notesAdapter);
        return rootView;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)    {
        NotesUID note = new NotesUID();
        Bundle extras = null;
        if (data != null) {
            extras = data.getExtras();
        }
        try {
            if ({更換Cursor,對應在資料庫中更換資料表}) {
                getLoaderManager().destroyLoader(oldLoaderId);
                getLoaderManager().initLoader(newLoaderId, null, this);
            } else if ({重新整理Cursor}) {
                getLoaderManager().restartLoader(oldLoader,null,this);
            }
        } catch (Exception e) {
            Log.e("PlaceholderFragment onActivityResult","error:"+e.getMessage());
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (mNotesCursor != null)
            mNotesCursor.close();
    }

    @Override
    // Called when a new Loader needs to be created
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        // Now create and return a CursorLoader that will take care of
        // creating a Cursor for the data being displayed.
        Log.v("onCreateLoader","OK");
        return new NotesLoader(getActivity(), {通過id找到資料表名});
    }

    @Override
        // Called when a previously created loader has finished loading
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        // 這裡沒有使用SwapCursor,而是使用了changeCursor,因為ChangeCursor比較明確老的cursor會被關閉,
        //SwapCursor由於不太清楚機制,不太敢用
        Log.v("onLoadFinished","OK");
        notesAdapter.changeCursor(data);
        mNotesCursor = data;
    }


    @Override
    // Called when a previously created loader is reset, making the data unavailable
    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.
        Log.v("onLoaderReset","OK");
        notesAdapter.changeCursor(null);
    }
}


NotesLoader繼承AsyncTaskLoader