android Cursor的自动管理方式

  新手在使用数据库的时候,很容易忘记关闭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()方法。


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






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Studio中的内存管理优化是一个关键环节,它涉及到应用性能和用户体验。以下是一些关键技术和策略: 1. **垃圾回收机制(Garbage Collection, GC)**:Android使用Java语言,其后台有自动垃圾回收器,开发者不需要手动管理内存。了解并合理利用并发GC和Finalizer Behavior等特性,可以减少内存泄漏的可能性。 2. **引用计数**:避免循环引用,这导致对象无法被垃圾回收,影响内存使用。及时解除不必要的引用连接很重要。 3. **内存泄漏检测**:使用Android Studio的Memory Profiler工具,可以帮助找出代码中可能存在的内存泄漏点。 4. **避免过度持有**:尤其是对于Activity、Fragment和BroadcastReceiver等组件,需要确保在生命周期结束时正确地取消对资源的引用。 5. **对象池和复用**:为频繁创建和销毁的对象使用对象池,可以减少内存分配和回收的开销。 6. **避免过多的全局变量和静态变量**:这些可能导致内存泄露,尤其是在长时间运行的服务中。 7. **使用WeakReference或SoftReference**:当需要弱引用其他对象,但又不希望阻止垃圾回收时,可以使用这些。 8. **避免过多的数据加载**:按需加载和数据压缩也能有效节省内存。 9. **谨慎使用Bitmap和Cursor**:优化图片加载,使用合适的格式和大小,并及时释放不再使用的Cursor。 10. **优化布局**:减少视图层次和重绘操作,尽量使用ViewGroup来替代LinearLayout等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值