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("我是接口,我不是空的");
}
网友评论