当前位置:   article > 正文

Android造成内存泄漏原因及解决方案_mcontext in linearlayout@316240896

mcontext in linearlayout@316240896

开发app中对内存的使用,一定是大家最关心的问题之一,因为内存的使用直接影响到app的性能。

内存使用中内存泄漏是开发Android应用中常见的,Android中可以使用LeakCanary来检测内存泄漏。

 

那么什么是内存泄漏?

内存泄漏简单解释就是:完全无用的对象,无法被被GC回收的现象就是内存泄漏。

 

内存泄漏会造成什么问题呢?

每个app可分配的内存是有限的,内存泄漏就会占有一块内存,过多的内存泄漏就会导致内存超出app可用的内存,导致内存溢出,app就奔溃了(引发Out Of Memory)。

 

接下来我们带着三个问题来分析下内存泄漏:

1.经常会出现内存泄漏的地方有哪些?

2.为什么会出现?

3.如何避免内存泄漏?

 

一.单例模式造成的内存泄漏:

  1. public class Signleton {
  2.     private static Signleton mSignleton;
  3.     private Context mContext;
  4.     private Signleton(Context context){
  5.         this.mContext = context;
  6.     }
  7.     public static Signleton getInstance(Context context){
  8.         if (mSignleton == null){
  9.             mSignleton = new Signleton(context);
  10.         }
  11.         return mSignleton;
  12.     }
  13. }

这里为什么会出现内存泄漏呢?

     因为单例模式的生命周期和应用程序是一样长的,所以当我们在一个activity中调用这个单例,传入activity作为context,单例就持有了这个activity的引用,而当我们退出这个activity时,由于单例的生命周期是同应用程序一样长,所以这个单例还持有activity的引用,这个activity对象就不会被回收,这时就造成了内存泄漏。

如何解决:

  1. private Signleton(Context context){
  2.     this.context = context.getApplicationContext();
  3. }

这里我们改成不管传入的context是activity还是其他的都转换为整个应用程序的context,这样生命周期就和单例一样长,就避免了内存泄漏。

 

二.非静态内部类造成的内存泄漏:  

  1. private final String TAG = "DemoActivity";
  2. private static Interior mInterior;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5.     super.onCreate(savedInstanceState);
  6.     setContentView(R.layout.activity_main2);
  7.     if (mInterior == null){
  8.         mInterior = new Interior();
  9.     }
  10. }
  11. class Interior{}

这里为什么会出现内存泄漏呢?

这个activity中有一个非静态内部类,因为非静态内部类中隐式持有外部类的引用,所以内部类Interior中就持有activity的引用,

例子中静态变量mInterior的生命周期是和应用程序一样长的,而该静态变量中又持有activity的引用,所以到activity销毁时,回收activity的时候无法被回收,就出现了内存泄漏。

如何解决:

  1. static class Interior{
  2. }

把该非静态内部类改成静态内部类就可以了(因为静态内部类不会持有外部的引用)。

 

三.Handler造成的内存泄漏:

  1. private void toHandler(){
  2.     mHandler.postDelayed(new Runnable() {
  3.         @Override
  4.         public void run() {
  5.             tvTitle.setText("hello");
  6.         }
  7.     },1000);
  8. }

这里为什么会出现内存泄漏呢?

这段代码中有两个方面会造成内存泄漏:

1.Runnable是匿名内部类,持有Activity的 TextView会造成内存泄漏。

2.TextView持有Activity 的强引用,这样也会造成内存泄漏。

因为handler的消息机制,当Activity销毁,handler中还有为处理的Message时就会持有activity的引用从而导致无法被回收,出现内存泄漏。

如何解决:

方法1:改成静态内部类+弱引用

  1. private static class DemoRunnable implements Runnable{
  2.     private WeakReference<TextView> wTextView;
  3.     protected DemoRunnable(TextView textView){
  4.         wTextView = new WeakReference<TextView>(textView);
  5.     }
  6.     @Override
  7.     public void run() {
  8.         wTextView.get().setText("hello");
  9.     }
  10. }

方法2:在Activity的onDestory中移除mHandler的所有Message

  1. @Override
  2. protected void onDestroy() {
  3.     super.onDestroy();
  4.     mHandler.removeCallbacksAndMessages(null);
  5. }

四.线程造成的内存泄漏:

线程的内存泄漏同Handler一样也是匿名内部类Runnable造成的,解决方式同handler方法1一样。

五.资源未关闭造成的内存泄漏:

主要使用的资源:

1.BraodcastReceiver

2.ContentObserver

3.File

4.Cursor

5.Stream

6.Bitmap

这些资源的使用都需要在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,从而造成内存泄漏。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/240364
推荐阅读
相关标签
  

闽ICP备14008679号