OnSharedPreferenceChangeListener调用失败之坑 强引用 软引用 弱引用 虚引用之分
来源:互联网 发布:淘宝定金尾款是同价格 编辑:程序博客网 时间:2024/06/08 18:29
引用这东西,之前一直都没怎么了解,从来不都是new对象的么,直到用 SharedPreference 的时候,碰到 OnSharedPreferenceChangeListener ,被坑了一把,才开始了解引用的概念,然后把玩一番。初看觉得这东西好麻烦,仔细了解一下之后才发现,这东西在内存控制方面还是很重要,很实用的(-_-||不过目前做的项目对内存方面几乎没有克制的要求,哈哈)。
故事是这样的,代码里将一个值存到 SharedPreference 里面,如果其他的地方改变这个值,我需要将新的值给显示出来,一个很简单的逻辑,可做完之后发现运行的结果与实际情况有时候会有出入,改动并没有被显示出来。分析来分析去,都觉得没问题啊,逻辑正常啊(程序员遇到bug都是这么想的)一直没有怀疑到监听失效这上面来。
后来经过打 log 发现,居然是,额,监听有时候有效,有时候无效,OnSharedPreferenceChangeListener 没有被触发。
第一次碰到这种监听无效的情况,一脸懵逼。
内部的项目的代码就不分享了,用一个 demo 来说明一下。
点击 Button,计数加1,将点击数存到 SharedPreference 中,用 OnSharedPreferenceChangeListener 来监听 SharedPreference 中值的变化,变化的时候将计数打印出来,在页面之前换来换去,运行一段时间会发现,OnSharedPreferenceChangeListener 失效了。
import android.content.SharedPreferences;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.widget.Button;import android.view.View;public class MainActivity extends AppCompatActivity { private SharedPreferences spJ; private SharedPreferences.Editor editor; private Button buttonNum; private int clickN; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final int initTimes=0; clickN=initTimes; buttonNum=(Button)findViewById(R.id.Button_Num);//获取按键控件 spJ =getApplicationContext().getSharedPreferences("ClickN",MODE_PRIVATE); editor= spJ.edit(); buttonNum.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { clickN++; editor.putInt("times",clickN).commit(); } }); spJ.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { Log.d("MainActivity ", "onSharedPreferenceChanged: " + spJ.getInt("times",initTimes)); } }); }}
XML 就不贴了,多简单的一个 demo 啊,这么简单的代码,居然还会失效,额,也是醉了。
不过看了源码中关于 registerOnSharedPreferenceChangeListener 的描述后,也就不觉得奇怪了,居然,用的,是,弱引用,真的是够坑的。
OK了,下面区分一下强引用,软引用,弱引用,虚引用之间的区别吧
强引用
从名字也很好理解,就是很强的引用咯,那么她有多强呢?即使在内存很紧缺的情况下,即使程序报出 Out Of Memory 错误,它也不会被回收的。这种我们在编程中用的是最广了,比如说 new,基本上大部分的对象都是强引用了。
软引用
软引用,顾名思义,就是比较弱的一种引用,弱是相对于上一个来说的。这个还是比较讲义气的,当内存不够用的时候,它会牺牲自己,贡献出占用的内存,避免发生 Out Of Memory。当内存足够时,它是比较安全的,并不会被回收掉。
弱引用
弱引用,就是比较弱咯,弱到什么程度呢,如果一不小心,被垃圾回收机制检测到,就被回收,貌似跟此时内存够不够没有关系。反正跟垃圾回收机制的关系很不好,见面就是掐啊。
虚引用
这个,就比较奇葩了,因为比弱还弱,弱到什么程度呢。对对象的生命周期没有影响,而且,无法通过弱引用得到对象,弱的不要不要的。它基本只有一个作用,在对象被回收的时候,得到一个系统通知,这一点,也是它唯一可以被利用的一点,也是最关键的一点。
怎么用呢?在需要对内存十分克制的开发中,这一点很重要,可以通过这一点来准确的判断对象是否被回收,来决定是否申请一个新的对象来占用内存。准确是相对通常用的 finalize() 方法来说的。
finalize() 被调用的时候,只是准备好释放存储空间,只有在下一次垃圾收集的过程中,对象的内存才会被清除掉,并不准确。还有一点,存在 finalize() 重写不规范的情况,如果在该方法中又创建了一个强引用来指向要被销毁的对象时,这个对象就重新复活了,运行 finalize() 之后并不会被干掉。
而使用虚引用就不会存在这种问题,只有当对象占用的内存空间被清除的时候,才会返回系统通知,这个时候,被销毁的对象是不会被重新激活的。这个消息才是最精确的。
解决方法
知道原理,要改这前的那个 bug 就好办了,既然是安卓,那就结合安卓 activity 的生命周期,在 onPause( ) 的时候主动注销监听,在 onResume()的时候创建监听就可以了。其实解这个 bug 还有其他的方法,有兴趣的读者可以自己去试一下。
@Override public void onPause() { spJ.unregisterOnSharedPreferenceChangeListener(profileChangedSPListener); super.onPause(); } @Override public void onResume() { spJ.registerOnSharedPreferenceChangeListener(profileChangedSPListener); super.onResume(); }
好了,到处都是坑,这就对了,不然哪来那么多的 bug 解,哈哈哈。
- OnSharedPreferenceChangeListener调用失败之坑 强引用 软引用 弱引用 虚引用之分
- java之强引用、弱引用、软引用、虚引用
- Java之:强引用、弱引用、软引用、虚引用
- Android修炼之道—Java之强引用、软引用、弱引用、虚引用
- JAVA之强引用,弱引用,软引用 与 JVM
- Java 7之基础 - 强引用、弱引用、软引用、虚引用
- Java基础之强引用,软引用,弱引用,虚引用
- Java 7之基础 - 强引用、弱引用、软引用、虚引用
- Java 7之基础 - 强引用、弱引用、软引用、虚引用
- Java7之基础-强引用、弱引用、软引用、虚引用
- Java 7之基础 - 强引用、弱引用、软引用、虚引用
- Java 7之基础 - 强引用、弱引用、软引用、虚引用
- Java 7之基础 - 强引用、弱引用、软引用、虚引用
- Java 7之基础 - 强引用、弱引用、软引用、虚引用
- Java 7之基础 - 强引用、弱引用、软引用、虚引用
- Java 7之基础 - 强引用、弱引用、软引用、虚引用
- Java 7之基础 - 强引用、弱引用、软引用、虚引用
- Java基础之强引用、弱引用、软引用、虚引用
- ASM red_hat4地址
- Linux学习笔记(三)_网络
- linux0.11内核完全剖析- fork.c
- JAVA关键字this和super作用与案例
- vue项目,引入elementUI没有样式,报错如下图,是好像是少了什么支持文件
- OnSharedPreferenceChangeListener调用失败之坑 强引用 软引用 弱引用 虚引用之分
- 多线程之间实现
- Android studio默认安装路径?
- leetcode 401. Binary Watch 一个十分经典的DFS深度优先遍历的做法
- QT控件大全五QProgressIndicator
- overflow 清除浮动
- docker RunC Create 源码简单分析
- 成员函数作为回调函数
- javascript 正则表达式大全