`
zhy20045923
  • 浏览: 156658 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

android中的Handler和AsyncTask如何防止内存泄露

 
阅读更多
Handler泄露的关键点有两个:

    1). 内部类

    2). 生命周期和Activity不一定一致

    第一点,Handler使用的比较多,经常需要在Activity中创建内部类,所以这种场景还是很多的。

    内部类持有外部类Activity的引用,当Handler对象有Message在排队,则无法释放,进而导致Activity对象不能释放。

    如果是声明为static,则该内部类不持有外部Acitivity的引用,则不会阻塞Activity对象的释放。

    如果声明为static后,可在其内部声明一个弱引用(WeakReference)引用外部类。
public class MainActivity extends Activity {
    private CustomHandler mHandler;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mHandler = new CustomHandler(this);
    }
 
    static class CustomHandlerextends Handler {
        // 内部声明一个弱引用,引用外部类
        private WeakReference<MainActivity > activityWeakReference;
        public MyHandler(MyActivity activity) {
            activityWeakReference= new WeakReference<MainActivity >(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            MyActivity act= activityWeakReference.get();
            if (activityWeakReference!= null && act!= null) {
                // ......
            }
        }
                // ... ...   
    }
}

第二点,其实不单指内部类,而是所有Handler对象,如何解决上面说的Handler对象有Message在排队,而不阻塞Activity对象释放?

    解决方案也很简单,在Activity onStop或者onDestroy的时候,取消掉该Handler对象的Message和Runnable。

    通过查看Handler的API,它有几个方法:removeCallbacks(Runnable r)和removeMessages(int what)等。
/ 一切都是为了不要让mHandler拖泥带水
@Override
public void onDestroy() {
    mHandler.removeMessages(MESSAGE_1);
    mHandler.removeMessages(MESSAGE_2);
    mHandler.removeMessages(MESSAGE_3);
    mHandler.removeMessages(MESSAGE_4);
 
    // ... ...
 
    mHandler.removeCallbacks(mRunnable);
 
    // ... ...
}

上面的代码太长?好吧,出大招:
@Override
public void onDestroy() {
    //  If null, all callbacks and messages will be removed.
    mHandler.removeCallbacksAndMessages(null);
}


AsyncTask的泄露和Handler类似,避免方法如下:
一 适当使用弱引用:
static class DisableChanger extends AsyncTask<Object, Object, Object> {
  final PackageManager mPm;
  final WeakReference<InstalledAppDetails> mActivity;
  final ApplicationInfo mInfo;
  final int mState;

  DisableChanger(InstalledAppDetails activity, ApplicationInfo info, int state) {
      mPm = activity.mPm;
      mActivity = new WeakReference<InstalledAppDetails>(activity);
      mInfo = info;
      mState = state;
  }
    }

二在activity退出时,终止asynctask任务:
具体退出方法如下:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             // 注意下面这行,如果检测到cancel,则及时退出
             if (isCancelled()) break;
         }
         return totalSize;
     }
 
     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }
 
     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }

官方的例子是很好的,在后台循环中时刻监听cancel状态,防止没有及时退出。
分享到:
评论

相关推荐

    android 中Handler 的几种写法

    在Android开发中,`Handler`是一个至关重要的组件,它用于在主线程中处理来自其他线程的消息,确保UI更新和事件处理的同步性。本文将详细介绍`Handler`的几种常见写法,以及如何使用`Handler.Callback`进行消息处理...

    Android中handler的使用

    在Android开发中,Handler是处理多线程通信的关键机制,尤其在UI更新和异步任务中扮演着重要角色。本文将深入探讨Handler的工作原理、如何使用以及它在处理多线程中的应用。 Handler的主要功能是发送和处理消息,它...

    Android-详细解读AsyncTask的黑暗面以及一种替代方案

    综上所述,虽然AsyncTask在早期Android开发中发挥了重要作用,但随着Android系统的演进和开发者对性能优化的追求,我们需要认识到它的局限性,并考虑采用更为健壮和灵活的解决方案。在实际项目中,应根据具体需求和...

    简介Android 中的AsyncTask

    为了避免这种情况,开发者需要在Activity的onDestroy()方法中正确地取消AsyncTask,或者使用 WeakReference 保持对Activity的引用以防止内存泄漏。 AsyncTask的执行流程主要包括以下几个步骤: 1. `onPreExecute()...

    Android和Handler那些事

    在Android开发中,`Handler`是一个非常重要的组件,它与线程通信密切相关,尤其是在处理UI更新和异步任务上起到关键作用。这篇博客"Android和Handler那些事"深入探讨了`Handler`的工作原理及其在实际应用中的使用...

    Android异步请求之AsyncTask

    2. **生命周期**:`AsyncTask`与Activity的生命周期绑定,如果在Activity中启动了一个`AsyncTask`,在Activity销毁前需要取消任务,否则可能导致内存泄漏。 3. **版本兼容**:自Android 3.0(API级别11)开始,`...

    模范Android中的AsyncTask

    - 当Activity销毁时,如果不取消`AsyncTask`,可能会导致内存泄漏或崩溃,因为`AsyncTask`可能尝试在已销毁的Activity上下文中更新UI。 3. **使用AsyncTask的注意事项** - 由于`AsyncTask`默认使用内部的线程池,...

    Android 用handler机制联网获取图片.zip

    6. **优化内存管理**:考虑到Android内存限制,需要正确释放资源,如使用Bitmap的recycle()方法回收不再使用的Bitmap,防止内存泄漏。 7. **异常处理**:确保在网络请求失败或发生异常时,有适当的错误处理机制,如...

    Android中的Handler的具体用法

    - 使用完`Handler`后,记得移除所有消息和回调,防止内存泄漏。 了解了`Handler`的工作原理和用法后,我们可以通过阅读源码来进一步理解它的内部实现。`Handler`、`Message`和`Looper`的源码中包含了详细的逻辑...

    AndroidApp定位和规避内存泄露方法研究

    5. Handler、Thread或AsyncTask:它们内部持有对Looper、MessageQueue和Handler对象的引用,若不妥善处理,可能导致内存泄露。 针对这些内存泄露,我们可以采取以下方法进行定位和规避: 1. 使用工具:Android ...

    android中handler的使用

    - **内存泄漏**:`Handler`持有对上下文的引用,如果不在适当的时候释放,可能导致Activity或Service无法正常回收,引发内存泄漏。使用弱引用`WeakReference`可以避免这个问题。 - **主线程阻塞**:过度使用`Handler...

    android_Handler整理总结

    但需要注意,过多的Handler交互可能会导致内存泄漏,因此在不再需要Handler时,记得调用`removeCallbacksAndMessages(null)`来清除消息队列,防止内存泄漏。 此外,Handler配合AsyncTask或者IntentService也是常见...

    Android_Handler01-源码.rar

    5. **AsyncTask**: 虽然Handler/Looper/Message是基础的线程通信方式,但Android还提供了AsyncTask,它是轻量级的异步任务框架,简化了简单的后台操作和UI更新。然而,对于复杂任务,理解并使用Handler机制仍然是...

    thread-handler-asynctask-demo

    "thread-handler-asynctask-demo"这个项目是一个关于Java线程和异步任务处理的示例,主要用于演示如何在Android环境中有效地管理后台任务以避免阻塞主线程。 1. **线程基础** - **线程**:线程是程序执行的最小...

    Android源代码:HandlerDemo

    7. **关闭Looper**:如果在自定义线程中使用了`Looper.prepare()`和`Looper.loop()`,记得在不再需要消息循环时调用`Looper.quit()`,防止内存泄漏。 理解并熟练运用`Handler`机制对于开发高效、稳定的Android应用...

    Android Handler模拟进度条更新

    注意,为了防止内存泄漏,记得在Activity或Fragment销毁时移除Handler的回调: ```java @Override protected void onDestroy() { super.onDestroy(); mHandler.removeCallbacksAndMessages(null); // 移除所有待...

    Looper-Handler-AsyncTask

    需要注意的是,由于内存泄漏和性能问题,从Android 3.0(API级别11)开始,`AsyncTask`不再推荐在静态内部类或应用单例中使用。 `Looper-Handler-AsyncTask`的组合是Android开发中处理异步操作的常见方式。`...

    Android开发工程师面试题之handler详解。android程序员,android开发面试资料,详解

    2. **如何避免Handler内存泄漏?** - 使用静态内部类定义Handler。 - 在Handler中使用弱引用指向外部Activity或其他对象。 - 明确释放资源,例如取消发送的消息等。 3. **Looper和Thread的关系?** - 每个...

    Android防止内存溢出浅析

    在Android开发中,防止内存溢出是一个至关重要的任务,因为Android设备的内存资源相对有限,尤其是在Dalvik虚拟机中,其最大堆大小通常只有16MB。本文将深入探讨Android平台上的内存管理机制,以及如何避免内存泄露...

Global site tag (gtag.js) - Google Analytics