使用AsyncTaskLoader動態載入SQLite資料
阿新 • • 發佈:2019-02-19
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