TA的每日心情 | 无聊 2024-9-19 09:07 |
---|
签到天数: 11 天 连续签到: 2 天 [LV.3]测试连长
|
2#
楼主 |
发表于 2017-8-15 13:34:57
|
只看该作者
单例模式泄露
- 分析:通过截图我们发现SplashActivity被ActivityUtil的实例activityStack持有
- 引用代码:
- ActivityUtil.getAppManager().add(this);
复制代码 持有代码:
- public void add(Activity activity) {
- if (activityStack == null) {
- synchronized (ActivityUtil.class){
- if (activityStack == null) {
- activityStack = new Stack<>();
- }
- }
- }
- activityStack.add(activity);
- }
复制代码
- 解决方案:
- 在SplashActivity的onDestroy()生命周期移除引用
- @Override
- protected void onDestroy() {
- super.onDestroy();
- ActivityUtil.getAppManager().remove(this);
- }
复制代码
静态变量持有Context实例泄露
- 分析:长生命周期持有短什么周期引用导致泄露,详见上文四大组件Context和Application的context使用
- 示例引用代码:
- private static HttpRequest req;
- public
- static void HttpUtilPost(Context context, int TaskId, String url,
- String requestBody,ArrayList<HttpHeader> Headers, RequestListener
- listener) {
- // TODO Auto-generated constructor stub
- req = new HttpRequest(context, url, TaskId, requestBody, Headers, listener);
- req.post();
- }
复制代码
解决方案:
- 改为弱引用
- pass:弱引用随时可能为空,使用前先判空
- 示例代码:
- public static void cancel(int TaskId) {
- if(req != null && req.get() != null){
- req.get().AsyncCancel(TaskId);
- }
- }
复制代码- private static WeakReference<HttpRequest> req;
- public
- static void HttpUtilPost(Context context, int TaskId, String url,
- String requestBody,ArrayList<HttpHeader> Headers, RequestListener
- listener) {
- // TODO Auto-generated constructor stub
- req = new WeakReference<HttpRequest>(new HttpRequest(context, url, TaskId, requestBody, Headers, listener));
- req.get().post();
- }
复制代码 改为长生命周期
- private static HttpRequest req;
- public
- static void HttpUtilPost(Context context, int TaskId, String url,
- String requestBody,ArrayList<HttpHeader> Headers, RequestListener
- listener) {
- // TODO Auto-generated constructor stub
- req = new HttpRequest(context.getApplicationContext(), url, TaskId, requestBody, Headers, listener);
- req.post();
- }
复制代码
Context泄露
Callback泄露
服务未解绑注册泄露
- 分析:一般发生在注册了某服务,不用时未解绑服务导致泄露
- 引用代码:
- private void initSensor() {
- // 获取传感器管理器
- sm = (SensorManager) container.activity.getSystemService(Context.SENSOR_SERVICE);
- // 获取距离传感器
- acceleromererSensor = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY);
- // 设置传感器监听器
- acceleromererListener = new SensorEventListener() {
- ......
- };
- sm.registerListener(acceleromererListener, acceleromererSensor, SensorManager.SENSOR_DELAY_NORMAL);
- }
复制代码
- 解决方案:
- 在Activity的onDestroy()方法解绑服务
- @Override
- protected void onDestroy() {
- super.onDestroy();
- sm.unregisterListener(acceleromererListener,acceleromererSensor);
- }
复制代码
Handler泄露
- 分析:由于Activity已经关闭,Handler任务还未执行完成,其引用了Activity的实例导致内存泄露
- 引用代码:
handler.sendEmptyMessage(0);- 解决方案:
- 在Activity的onDestroy()方法回收Handler
- @Override
- protected void onDestroy() {
- super.onDestroy();
- handler.removeCallbacksAndMessages(null);
- }
复制代码
异步线程泄露
- 分析:一般发生在线程执行耗时操作时,如下载,此时Activity关闭后,由于其被异步线程引用,导致无法被正常回收,从而内存泄露
- 引用代码:
- new Thread() {
- public void run() {
- imageArray = loadImageFromUrl(imageUrl);
- }.start();
复制代码
- 解决方案:
- 把线程作为对象提取出来
- 在Activity的onDestroy()方法阻塞线程
后面- 欢迎补充实际中遇到的泄露类型
- 文章如有错误,欢迎指正
- 如有更好的内存泄露分享方法,欢迎一起讨论
|
|