本文介绍: 常见内存泄漏场景1、非静态内部类的静态实例静态内部类会持有外部实例引用,如果非静态内部类的实例静态的,就会间接的长期维持着外部类的引用,阻止被系统回收public class TestActivity extends Activity { private static Object inner = null; @Override protected void onCreate(Bundle savedInstanceState) { supe

常见内存泄漏场景

1、非静态内部类的静态实例

静态内部类会持有外部类实例的引用,如果非静态内部类的实例是静态的,就会间接的长期维持着外部类的引用,阻止被系统回收。

public class TestActivity extends Activity {
    private static Object inner = null;
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                createInnerClass();
                finish();
            }
        });
    }

    private void createInnerClass() {
        class InnerClass {
        }
        inner = new InnerClass();//1
    }
}

点击Button时,会创建非静态内部类InnerClass的静态实例inner,该实例的生命周期会和应用程序一样长,并且会一直持有TestActivity 的引用,导致TestActivity无法被回收。

2、匿名内部类持有外部类的引用

匿名内部类也会持有外部类实例的引用

public class TestActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startAsyncTask();
                finish();
            }
        });
    }
    void startAsyncTask() {
        new AsyncTask<Void, Void, Void&gt;() {//1
            @Override
            protected Void doInBackground(Void... params) {
                while (true) ;
            }
        }.execute();
    }
}

解决方案:改成静态内部类来实现

3、Bitmap对象

临时创建的某个相对比较大的bitmap对象,在经过变换得到新的bitmap对象之后,应该尽快回收原始的bitmap,这样能够更快释放原始bitmap占用空间
避免静态变量持有比较大的bitmap对象或者其他大的数据对象,如果已经持有,要尽快置空该静态变量

4、WebView

不同的Android版本的WebView会有差异,加上不同厂商定制ROM的WebView的差异,这就导致WebView存在着很大的兼容性问题。WebView都会存在内存泄漏问题,在应用中只要使用一次WebView,内存就不会被释放掉。通常的解决办法就是为WebView单开一个进程使用AIDL与应用的主进程进行通信。WebView进程可以根据业务需求,在合适的时机进行销毁。

5、资源对象未关闭

资源对象比如Cursor、File等,往往都用了缓冲,不使用时候应该关闭它们。把他们的引用置为null,而不关闭它们,往往会造成内存泄漏。因此,在资源对象不使用时,一定要确保它已经关闭,通常在finally语句中关闭,防止出现异常时,资源未被释放的问题

6、集合中对象没清理

通常把一些对象的引用加入到了集合中,当不需要该对象时,如果没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就会更加严重。

7、监听器未关闭

很多系统服务比如TelephonyMannager、SensorManager)需要register和unregister监听器我们需要确保在合适的时候及时unregister那些监听器自己手动add的Listener,要记得在合适的时候及时remove这个Listener。

8、未正确使用Context导致被持有

对于不是必须使用Activity Context的情况(Dialog的Context就必须是Activity Context),我们可以考虑使用Application Context来代替Activity的Context,这样可以避免Activity泄露比如如下单例模式

public class AppSettings { 
 private Context mAppContext;
 private static AppSettings mAppSettings = new AppSettings();
 public static AppSettings getInstance() {
  return mAppSettings;
 }

 public final void setup(Context context) {
  mAppContext = context;
 }
 }

mAppSettings作为静态对象,其生命周期会长于Activity。当进行屏幕旋转时,默认情况下,系统会销毁当前Activity,因为当前Activity调用setup方法,并传入了Activity Context,使得Activity被一个单例持有,导致垃圾收集器无法回收,进而产生了内存泄露
解决方法就是使用Application的Context或者是使用弱引用:

public final void setup(Context context) {
 mAppContext = context.getApplicationContext(); 
}                                 

原文地址:https://blog.csdn.net/kuankuan199308153614/article/details/123232102

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_28476.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注