android 实例-弱引用示例 Handler正确使用方法
实际问题
android 习惯性问题:在使用handler的时候喜欢使用内部类形式。
private final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// ...
}
};
看一下问题代码和现象:
package zol.com.zolcamera; import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View; public class AActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
mHandler.sendEmptyMessageDelayed(0, 2000);
} Handler mHandler = new Handler() { @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mHandler.sendEmptyMessageDelayed(0, 2000);
}
}; @Override
protected void onResume() { super.onResume();
}
}
package zol.com.zolcamera; import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View; public class BActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(BActivity.this, AActivity.class);
startActivity(intent);
}
});
}
}
上面两个Activity B跳到A 再点button回A 。重复几次。再看一下内存情况。

可以看到内存当中有好几个AActivity,并没有释放。
如果你使用android studio 当你写出这样的代码的时候,IDE会提示你这样写法会造成内存泄漏。
原因是:内部实例会持有外部类引用。
当Activity finish的时候如果handler没有在工作,没有延时消息,那么问题不大,否则是finish不掉的。
第一种解决办法,声明成静态。内部静态类不持有外部类引用。
第二种解决法,换一种写法,不声明成内部类。
package zol.com.zolcamera; import android.os.Handler;
import android.os.Message; /**
* Created by Administrator on 2018/3/8.
*/ public class MyHandler extends Handler { AActivity mAActivity; public MyHandler(AActivity aActivity) {
mAActivity = aActivity;
} @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
sendEmptyMessageDelayed(0, 2000);
} public void clear() {
mAActivity = null;
removeCallbacksAndMessages(null);
}
}
这里手动做了对Activity的置空。如果不放心那就用软件引用。
/**
* 声明一个静态的Handler内部类,并持有外部类的弱引用
*/
private static class MyHandler extends Handler{ private final WeakReference<HandlerActivity> mActivty; private MyHandler(HandlerActivity mActivty) {
this.mActivty = new WeakReference<HandlerActivity>(mActivty);
} @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
HandlerActivity activity = mActivty.get();
if (activity != null){
// .... }
}
}
问题二:在主线程直接new Handler 使用的是主线程Looper.如果handler工作频率很高,会影响主线程的效率。
所以某些UI操作 (对,ui操作)使用线程来执行。
大家都知道Thread + Handler 来实现。在子线程里new handler 必须先准备Looper.调用Looper.prepar()才能用。
google给大家其实已经提供了现成的,那就是HandlerThread ;

@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
这才是准备looper的正确姿势。
下面声明Handler
private HandlerThread handlerThread;
private Handler mHandler;
public void initHandler() {
handlerThread = new HandlerThread("camera");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper(), mCallback);
}
这个handler才是最好的。
package zol.com.zolcamera; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View; public class AActivity extends AppCompatActivity implements View.OnClickListener { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
findViewById(R.id.bt).setOnClickListener(this);
initHandler();
mHandler.sendEmptyMessageDelayed(0, 2000);
} private HandlerThread handlerThread;
private Handler mHandler; public void initHandler() {
handlerThread = new HandlerThread("camera");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper(), mCallback);
} Handler.Callback mCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
return false;
}
}; @Override
public void finish() {
mHandler.removeCallbacksAndMessages(null);
super.finish();
} @Override
public void onClick(View v) {
finish();
} @Override
protected void onResume() { super.onResume();
}
}
退出时做如下操作。
@Override
public void finish() {
mHandler.removeCallbacksAndMessages(null);
super.finish();
}
理论是可以了。
以上内容只经过简单试验,有问题请看官自行研究。或与本人讨论。
android 实例-弱引用示例 Handler正确使用方法的更多相关文章
- android WeakReference(弱引用 防止内存泄漏)与SoftReference(软引用 实现缓存机制(cache))
在Android开发中,基本上很少有用到软引用或弱引用,这两个东东若用的很好,对自己开发的代码质量的提高有很大的帮助.若用的不好,会坑了自己.所以,在还没有真正的去了解它们之前,还是慎用比较好. 下面 ...
- Android一个工程引用另一个工程的方法
一个工程包含另一个工程.相当于一个jar包的引用.但又不是jar包反而像个package 现在已经有了一个Android工程A.我们想扩展A的功能,但是不想在A的基础上做开发,于是新建了另外一个And ...
- Swift 弱引用与无主引用
前言 Swift 提供了两种解决循环引用的方法,弱引用和无主引用. 弱引用和无主引用可以使循环中的一个实例引用另一个实例时不使用强引用. 1.弱引用 对生命周期中会变为 nil 的实例采用弱引用,也就 ...
- 说说WeakReference弱引用
WeakReference弱引用概述 http://www.cnblogs.com/xrq730/p/4836700.html,关于Java的四种引用状态具体请参看此文 Java里一个对象obj被创建 ...
- Android 弱引用和软引用
软引用 和 弱引用 1. SoftReference<T>:软引用-->当虚拟机内存不足时,将会回收它指向的对象:需要获取对象时,可以调用get方法. 2. WeakRefere ...
- Android中的WeakReference 弱引用
WeakReference 弱引用 定义:弱引用,与强引用(我们常见的引用方式)相对:特点是:GC在回收时会忽略掉弱引用对象(忽略掉这种引用关系),即:就算弱引用指向了某个对象,但只要该对象没有被强引 ...
- C++中弱符号(弱引用)的意义及实例
今天读别人代码时看到一个“#pragma weak”,一时没明白,上网研究了一个下午终于稍微了解了一点C.C++中的“弱符号”,下面是我的理解,不正确的地方望大家指正. 本文主要从下面三个方面讲“弱符 ...
- Android性能提升之强引用、软引用、弱引用、虚引用使用
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52637333 背景:收到公众投稿 ...
- Android学习笔记之SoftReference软引用,弱引用WeakReference
SoftReference可以用于bitmap缓存 WeakReference 可以用于handler 非静态内部类和匿名内部类容易造成内存泄漏 private Handler mRemoteHand ...
随机推荐
- Docker Ubuntu容器安装ping
apt-get update apt-get install iputils-ping apt-get install net-tools
- TP-LINK WR941N路由器研究
TP-LINK WR941N路由器研究 之前看到了一个CVE, CVE-2017-13772 是TP-Link WR940N后台的RCE, 手头上正好有一个TP-Link WR941N的设备,发现也存 ...
- Redis的keyspace notification(键空间通知)
文章来源https://www.cnblogs.com/tinywan/p/5903988.html 一.需求分析: 设置了生存时间的Key,在过期时能不能有所提示? 如果能对过期Key有个监听,如何 ...
- STM32WB SRAM2
SRAM2存储: 1.挂接总线及地址大小 2.地址镜像 3.RDP(read protection)等级 4.不同等级下的访问状态 5.声明位于SRAM2区中的数据 1)在icf文件中定义region ...
- zabbix4.2Proxy安装文档
zabbix4.2Proxy安装文档 目录 zabbix4.2Proxy安装文档 1 一.安装 2 1.前期安装准备 2 2.安装zabbix RPM源 3 2.1下载zabb ...
- 内置函数 lambda sorted filter map 递归
一 lambda 匿名函数 为了解决一些简单的需求而设计的一句话函数 # 计算 n 的 n次方 def func(n): return n**n print(func(10)) f = lambda ...
- C语言-数字字符串转换成这个字符串对应的数字(十进制、十六进制)
数字字符串转换成这个字符串对应的数字(十进制.十六进制) (1)数字字符串转换成这个字符串对应的数字(十进制) 要求:这个字符串参数必须包含一个或者多个数字,函数应该把这些数字转换为整数并且返回这个整 ...
- js页面重定向跳转代码总结(待续)
情形一:东八区,浏览器中文跳转 <script type="text/javascript"> var sLang = (navigator.language ? na ...
- Linux之RPM 软件管理程序
RPM RPM是软件管理程序,提供软件的安装.升级.查询.反安装的功能.优点:a.安装方便,软件中所有数据都经过编译和打包b.查询.升级.反安装方便缺点:a.缺乏灵活性b.存在相依属性 用法: rpm ...
- hexo个人博客添加宠物/鼠标点击效果/博客管理
1.添加宠物 博客宠物模型:https://github.com/xiazeyu/live2d-widget-models 模型对应的动画效果:https://huaji8.top/post/live ...