StrictMode检测Android中的违规代码 (二)(内存泄露,IO操作,网络操作)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq998701/article/details/84546901

1.内存泄露问题对一个app的使用影响还是挺大的,建议重点关注。

2.今天再看个非静态内部类或者匿名内部类导致的内存泄露问题。

(1)app从A页面跳转到B页面。在B页面有下面这样一段代码:

 private  Handler mhandle = new Handler() {
        @Override
        public void handleMessage(final Message msg) {

            runOnUiThread(new Runnable() { //主线程刷新
                @Override
                public void run() {

                    String obj = (String) msg.obj;
                    tvData.setText(obj);
                }
            });

        }
    };
  private void sendMsg() {
        tvSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(6000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        Message message = new Message();
                        message.obj = "datass";
                        mhandle.handleMessage(message);
                    }
                }).start();

            }
        });
    }

大致意思就是,B页面上有个按钮,点击发送handle消息,并且,在当前页面刷新Ui,设置发送的数据到一个textview里面。

A页面的跳转:


        tvGo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(MainActivity.this,Main2Activity.class));
            }
        });

(2)需要注意2点:第一:BActivity的mhandle是采用内部类的方式创建的,第二:发送handle消息是在子线程操作的,并且模拟了,耗时操作6s。6s后,发送消息,更新Ui。

3.上面的代码,在A页面点击跳转B页面,B页面按返回键,返回到B页面,来回切换2次以上,B页面的实例会越来越多,也就是说,B页面activity泄露了,资源没有全部释放。检测警告如下:

11-26 15:59:03.939 14797-14797/com.example.xyc.memoryleakapp E/StrictMode: class com.example.xyc.memoryleakapp.Main2Activity; instances=2; limit=1
    android.os.StrictMode$InstanceCountViolation: class com.example.xyc.memoryleakapp.Main2Activity; instances=2; limit=1
        at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)
11-26 15:59:07.056 14797-14797/com.example.xyc.memoryleakapp E/StrictMode: class com.example.xyc.memoryleakapp.Main2Activity; instances=3; limit=1
    android.os.StrictMode$InstanceCountViolation: class com.example.xyc.memoryleakapp.Main2Activity; instances=3; limit=1
        at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)
11-26 15:59:08.708 14797-14797/com.example.xyc.memoryleakapp E/StrictMode: class com.example.xyc.memoryleakapp.Main2Activity; instances=4; limit=1
    android.os.StrictMode$InstanceCountViolation: class com.example.xyc.memoryleakapp.Main2Activity; instances=4; limit=1
        at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)

4.这里需要注意的是,泄露原因是因为,Looper的MessageQueue里面还有未处理的消息Message,而Message又引用了mhandle,如果mhandle采用匿名内部类的方式创建,又会默认持有activity,所以消息未处理完,activity也释放不了。但是,当消息队列执行完(B页面执行6s后),当前activity是会自动回收掉的,资源可以被回收,如果这个消息是持久循环 发送就另说了。

5.解决办法:

方法一:通过程序逻辑来进行保护。
1.在关闭Activity的时候停掉你的后台线程。线程停掉了,就相当于切断了Handler和外部连接的线,Activity自然会在合适的时候被回收。 
2.如果你的Handler是被delay的Message持有了引用,那么使用相应的Handler的removeCallbacks()方法,把消息对象从消息队列移除就行了。 

方法二:将Handler声明为静态类。
PS:在Java 中,非静态的内部类和匿名内部类都会隐式地持有其外部类的引用,静态的内部类不会持有外部类的引用。
静态类不持有外部类的对象,所以你的Activity可以随意被回收。由于Handler不再持有外部类对象的引用,导致程序不允许你在Handler中操作Activity中的对象了。所以你需要在Handler中增加一个对Activity的弱引用(WeakReference)。


static class MyHandler extends Handler
    {
        WeakReference<Activity> mWeakReference;
        public MyHandler(Main2Activity activity) 
        {
            mWeakReference=new WeakReference< Main2Activity >(activity);
        }
        @Override
        public void handleMessage(Message msg)
        {
            final Activity activity=mWeakReference.get();
            if(activity!=null)
            {
                if (msg.what == 1)
                {
                    noteBookAdapter.notifyDataSetChanged();
                }
            }
        }
    }

猜你喜欢

转载自blog.csdn.net/qq998701/article/details/84546901