Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android Cursor的自動管理方式

android Cursor的自動管理方式

編輯:關於Android編程

新手在使用數據庫的時候,很容易忘記關閉Cursor,造成嚴重內存洩漏。有什麼好的方法解決這個問題呢?除了自己管理Cursor,有什麼辦法把Cursor交給系統管理,而不需要自己主動close呢?manageQuery可以為你維護這個cursor。在你退出activity時為你自動關閉。

The method managedQuery(Uri, String[], String, String[], String) from the type Activity is deprecated。

android官方文檔推薦用CursorLoader類來取代。

我們先來分析一下manageQuery是如何管理cursror的

 

 private static final class ManagedCursor {
        ManagedCursor(Cursor cursor) {
            mCursor = cursor;
            mReleased = false;
            mUpdated = false;
        }

        private final Cursor mCursor;
        private boolean mReleased;
        private boolean mUpdated;
    }
    private final ArrayList mManagedCursors =
        new ArrayList();

 

 

   public final Cursor managedQuery(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        Cursor c = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
        if (c != null) {
            startManagingCursor(c);
        }
        return c;
    }
    public void startManagingCursor(Cursor c) {
        synchronized (mManagedCursors) {
            mManagedCursors.add(new ManagedCursor(c));
        }
    }
  protected void onDestroy() {
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
        mCalled = true;

        // dismiss any dialogs we are managing.
        if (mManagedDialogs != null) {
            final int numDialogs = mManagedDialogs.size();
            for (int i = 0; i < numDialogs; i++) {
                final ManagedDialog md = mManagedDialogs.valueAt(i);
                if (md.mDialog.isShowing()) {
                    md.mDialog.dismiss();
                }
            }
            mManagedDialogs = null;
        }

        // close any cursors we are managing.
        synchronized (mManagedCursors) {
            int numCursors = mManagedCursors.size();
            for (int i = 0; i < numCursors; i++) {
                ManagedCursor c = mManagedCursors.get(i);
                if (c != null) {
                    c.mCursor.close();
                }
            }
            mManagedCursors.clear();
        }

        // Close any open search dialog
        if (mSearchManager != null) {
            mSearchManager.stopSearch();
        }

        getApplication().dispatchActivityDestroyed(this);
    }

看來這幾個方法就已經非常明確了。將cursor封裝之後放到一個ArrayList中,在Activity的Destroy方法中關閉cursor,Activity正常銷毀一定會走OnDestroy()方法的,這樣可以保證cursor會被關閉。

LoaderManager方法有下面幾個方面更勝一籌:

1. startManagingCursor管理Cursors,而LoaderManager管理Loader對象。Loader是一個模板類,D是一個包含了需要載入數據的類。也就是說,數據源並不必須是Cursor,它可以是List、JSONArray。。。任何類。LoaderManager與它包含的數據內容解耦了,所以更加靈活。

2. 調用startManagingCursor會導致Activity在已經加入管理的Cursor上調用requery()方法。在第一篇文章中提到過,在UI線程執行requery()方法代價非常高。相反的是,Loader的子類會異步載入(譯者注:另外再開一個線程,就叫異步了。)數據,所以使用LoaderManager永遠不會產生阻塞UI線程的情況。

3. startManagingCursor在配置變化(例如橫豎屏切換)時,並不會保持Cursor的狀態。麻煩的是,每次Activity由於配置變化(比如,簡單的橫豎屏切換),都會導致Cursor下回並且被重新查詢。LoaderManager就智能多了,當配置變化時,它會保持它裡面的Loader們的狀態,所以並不需要重新查詢數據。

4. LoaderManager提供無縫的數據監測。任何時候,當Loader的數據源改變,LoaderManager將會從對應的Loader上面接收到一個新的同步載入數據,並將更新數據返回給客戶端(注意:僅當Loader被正確實現,LoaderManager才會接收到這些數據變化通知。我們將會在該系列的第三篇文章討論自定義Loaders的實現)。

CursorLoader使用LoaderManager管理Cursor

使用方法如下

 

LoaderCallbacks callback= new  LoaderCallbacks() {

               @Override
               public Loader onCreateLoader(int id, Bundle args) {
                      // 返回自己需要的CursorLoader
                      return null ;
              }

               @Override
               public void onLoadFinished(Loader loader, Cursor data) {
                      // 使用swapCursor()方法,以使舊的游標不被關閉.
                      simpleCursorAdapter.swapCursor(cursor);
              }

               @Override
               public void onLoaderReset(Loader loader) {       、
                       // 一般寫這樣寫
                       simpleCursorAdapter.swapCursor(null);
              } 
}; 
getLoaderManager().initLoader(0, null, callback);

 

需要注意的是當使用initLoader()時,如果指定ID的裝載器已經存在,則它使用這個裝載器.如果不存在呢,它將創建一個新的.但是有時你卻是想丟棄舊的然後開始新的數據,要使用restartLoader()方法。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved