新手在使用数据库的时候,很容易忘记关闭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<ManagedCursor> mManagedCursors =        new ArrayList<ManagedCursor>();

   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<D>对象。Loader<D>是一个模板类,D是一个包含了需要载入数据的类。也就是说,数据源并不必须是Cursor,它可以是List、JSONArray。。。任何类。LoaderManager与它包含的数据内容解耦了,所以更加灵活。
2. 调用startManagingCursor会导致Activity在已经加入管理的Cursor上调用requery()方法。在第一篇文章中提到过,在UI线程执行requery()方法代价非常高。相反的是,Loader<D>的子类会异步载入(译者注:另外再开一个线程,就叫异步了。)数据,所以使用LoaderManager永远不会产生阻塞UI线程的情况。
3. startManagingCursor在配置变化(例如横竖屏切换)时,并不会保持Cursor的状态。麻烦的是,每次Activity由于配置变化(比如,简单的横竖屏切换),都会导致Cursor下回并且被重新查询。LoaderManager就智能多了,当配置变化时,它会保持它里面的Loader们的状态,所以并不需要重新查询数据。
4. LoaderManager提供无缝的数据监测。任何时候,当Loader的数据源改变,LoaderManager将会从对应的Loader上面接收到一个新的同步载入数据,并将更新数据返回给客户端(注意:仅当Loader被正确实现,LoaderManager才会接收到这些数据变化通知。我们将会在该系列的第三篇文章讨论自定义Loaders的实现)。

CursorLoader使用LoaderManager管理Cursor

使用方法如下

LoaderCallbacks<Cursor> callback= new  LoaderCallbacks<Cursor>() {               @Override               public Loader<Cursor> onCreateLoader(int id, Bundle args) {                      // 返回自己需要的CursorLoader                      return null ;              }               @Override               public void onLoadFinished(Loader<Cursor> loader, Cursor data) {                      // 使用swapCursor()方法,以使旧的游标不被关闭.                      simpleCursorAdapter.swapCursor(cursor);              }               @Override               public void onLoaderReset(Loader<Cursor> loader) {       、                       // 一般写这样写                       simpleCursorAdapter.swapCursor(null);              } }; getLoaderManager().initLoader(0, null, callback);

  

需要注意的是当使用initLoader()时,如果指定ID的装载器已经存在,则它使用这个装载器.如果不存在呢,它将创建一个新的.但是有时你却是想丢弃旧的然后开始新的数据,要使用restartLoader()方法。


欢迎扫描二维码,关注公众号






更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. 一句话锁定MySQL数据占用元凶
  3. android动态获取权限方法
  4. Android之Handler与线程
  5. 【Android(安卓)动画】帧动画、补间动画、属性动画
  6. 【攻克Android(安卓)(43)】WebView (网络视图)
  7. android中的数据存取 之 File
  8. Android(安卓)4.4 Kitkat Phone工作流程浅析(四)__RILJ工作流程
  9. Context 传递数据

随机推荐

  1. About sdk manager :error null
  2. 自动化脚本
  3. Android(安卓)Toast 简单封装
  4. JunitTest
  5. Ubuntu 10.04 LTS 安装 sun-java6-jdk 错
  6. Caused by: java.lang.NullPointerExcept
  7. [Android]检查当前手机是否有网络
  8. Steps To Compile TCC9301 Android(安卓)
  9. Android(安卓)监听屏幕锁屏,用户解锁
  10. imx515 开发板Android源代码编译过程