美文网首页
解决我对静态类/弱引用的理解的一些博客与内存泄露总结

解决我对静态类/弱引用的理解的一些博客与内存泄露总结

作者: 一个冬季 | 来源:发表于2019-03-12 09:28 被阅读0次

Java静态内部类的实例化问题
单例模式 - 只有一个实例
静态内部类什么时候被释放?会一直存在么?
关于弱引用WeakReference的一点疑问
静态方法与非静态方法的区别
静态内部类的生命周期
程序设计之单例模式VS静态方法
java静态方法和非静态方法的区别
弱引用——WeakReference——所引用的对象的回收规则

大量静态方法占很多内存么?

1、不管是静态方法,非静态方法都是占内存的
2、现在举个例子,A类含有100个静态方法,B类含有100非静态方法,当创建类/A.方法,所耗的内存都一样,唯一区别是,我B类长期不用就会被gc回收,A类里的方法就不同了,它会一直存在内存中
3、什么时候用静态方法,什么时候用单例呢?
如果你你一个方法利用率可以达到50%以上,你就可以考虑用静态方法,其它时候就用单例类

对 WeakReference 研究

对于弱引用我们经常看到类似如下这样的代码

 private TestNeiCunXieLouActivity mActivity;//某个activity
 public WeakReference<TestNeiCunXieLouActivity> weakReference;
    public TestRunner(TestNeiCunXieLouActivity activity) {
        weakReference = new WeakReference<TestNeiCunXieLouActivity>(activity);
        this.mActivity = weakReference.get();
    }

然后就说这样就可以解决内存泄漏的问题,当然了可能TestRunner 前面可能会加一个static。今天研究的是,我们不加static,只使用弱引用也可以解决内存泄漏的问题么??为了简单起见,代码能省就省

public class TestNeiCunXieLouActivity extends BaseActivity implements View.OnClickListener{
    private TestRunner testRunner;//一个线程类
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        init();
        setTitleHeader("测试内存泄漏");
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_test_neicunxielou;
    }

    @OnClick({R.id.bt_test_neicunxielou_neicunxielou})
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bt_test_neicunxielou_neicunxielou:{
                if (testRunner == null){
                    testRunner = new TestRunner(this);
                    new Thread(testRunner).start();
                }else {
                    testRunner.weakReference.clear();//清除引用
                    testRunner.weakReference.get();
                    testRunner.weakReference=null;
                }
            }
            break;
        }
    }
}

这里很简单TestRunner 是一个实现了Runnable的类

public class TestRunner implements Runnable{
    private String TAG = TestRunner.class.getSimpleName();
    private TestNeiCunXieLouActivity mActivity;
    public WeakReference<TestNeiCunXieLouActivity> weakReference;
    public TestRunner(TestNeiCunXieLouActivity activity) {
        weakReference = new WeakReference<TestNeiCunXieLouActivity>(activity);
        this.mActivity = weakReference.get();
    }

    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(1000);
                if (mActivity == null){
                    Log.i(TAG,"mActivity,是null 了");
                }else {
                    Log.i(TAG,"mActivity,我还没有变空哦,哈哈哈哈");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

当我们第一次直接点击按钮的时候,1秒过后就会打印, “mActivity,我还没有变空哦,哈哈哈哈”,过一会,我们直接第二次点击按钮,将弱引用清空,发现打印的日志, “mActivity,我还没有变空哦,哈哈哈哈”


点击第一次,点击第二次.png

此时我们点击返回按钮,不关闭线程,发现打印的日志, “mActivity,我还没有变空哦,哈哈哈哈”

总结:

第一次我们点击按钮这样获取Activity

 private TestNeiCunXieLouActivity mActivity;//某个activity
 public WeakReference<TestNeiCunXieLouActivity> weakReference;
    public TestRunner(TestNeiCunXieLouActivity activity) {
        weakReference = new WeakReference<TestNeiCunXieLouActivity>(activity);
        this.mActivity = weakReference.get();//获取到activity
    }

然后第二次点击按钮,清除弱应用

 testRunner.weakReference.clear();
 testRunner.weakReference.get();

最后发现还是能获取到Activity的引用,上面给的日志已经充分的证明了,说明,我们想清除持有Activity失败

解决办法

1、我们需要在activity类,重新复写onDestroy()

 @Override
    protected void onDestroy() {
        super.onDestroy();
        testRunner.onDestory();
    }

在线程类要自己写onDestory()方法

  public void onDestory(){
        weakReference.clear();
        this.mActivity = weakReference.get();
    }

此时获取到的weakReference.get() == null


没有引用了.png

这样就不会获取到activity的引用了,当然线程我还是没关闭的,这个不在我们讨论范围内

所以当我们通过这样获取到Actity引用的时候

 this.mActivity = weakReference.get();

需要通过这样的方法去除引用

   weakReference.clear();
   this.mActivity = weakReference.get();

2、直接操作weakReference.get()即可,不将其赋值给强引用的Activity

接口出现内存泄露解决办法

经过上面的测试,当我们通过弱引用获取到了Activity,并又强制赋值给当前类的全局Activity的时候,我们仍旧能持有activity。在这里接口的解决办法同上面的2种一样,我就只列举最简单的方式

  public WeakReference<ReadMsgListener> weakReference;
   public interface ReadMsgListener{
        void onGetMessageFromService(String value);
    }

    public void setUnReadMsgListener(ReadMsgListener xunReadMsgListener){
        weakReference = new WeakReference<ReadMsgListener>(xunReadMsgListener);
    }

    //接口回调
     if (weakReference.get() != null){
           weakReference.get().onGetMessageFromService("我是接口,我不是空的");
    }

相关文章

网友评论

      本文标题:解决我对静态类/弱引用的理解的一些博客与内存泄露总结

      本文链接:https://www.haomeiwen.com/subject/zbbtpqtx.html