观察 SharedPreferences 数据

2023-12-24

我正在尝试观察共享偏好中的数据变化。我找到了这个similar https://stackoverflow.com/questions/50649014/livedata-with-shared-preferences问题回答者@SimplyProgrammer https://stackoverflow.com/users/3409734/simplyprogrammer并按照他指示的步骤进行操作,但到了一天结束时,我的观察员仍然无法工作。

然后我决定寻求一些帮助以更好地理解原因。

这是我的实现

我首先实现抽象的实时数据

    SharedPreferences preference;
    String key;
    T defValue;

    public SharedPrefferenceLiveData(SharedPreferences preference,String key,T defValue){
        this.preference=preference;
        this.key=key;
        this.defValue=defValue;
    }

    private SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener=new SharedPreferences.OnSharedPreferenceChangeListener() {
        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            if(SharedPrefferenceLiveData.this.key.equals(key)){
                setValue(getValueFromPreferences(key,defValue));
            }
        }
    };
    abstract T getValueFromPreferences(String key, T defValue);

    @Override
    protected void onActive(){
        super.onActive();
        setValue(getValueFromPreferences(key,defValue));
        preference.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
    }

    @Override
    protected void onInactive() {
        preference.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
        super.onInactive();
    }
}

然后我实现了实时数据类型类

public class LocationLiveData extends SharedPrefferenceLiveData<String>{
    public LocationLiveData(SharedPreferences preferences, String key, String string){
        super(preferences,key,string);
    }

    @Override
    public String getValueFromPreferences(String key, String defValue) {
        return preference.getString(key,defValue);
    }
}

然后我将其添加到我的首选项管理类中,如下所示

实例化和设置 getter

private LocationLiveData sharedPreferenceLiveData;

public LocationLiveData getSharedPrefs(){
    return sharedPreferenceLiveData;
}

然后像这样分配值

 public void saveUserLocation(Location location){
        ...
        settings = context.getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
        editor = settings.edit();
        editor.putString(User_Location, currentLocation);
        editor.apply();
        sharedPreferenceLiveData=new LocationLiveData(settings,User_Location,currentLocation);
    }

然后在我的活动中,我像这样访问共享首选项 LiveData

    @Inject
    SharedPreference sharedPreference;
    ...
    ...
    LocationLiveData liveData;
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    ...
    ...
    ...
    liveData=sharedPreference.getSharedPrefs();
    ...
    ...
    observeMarkerLocation();
    }

    ...
    ...
    ...
    //the observer
    private void observeMarkerLocation() {
        if(liveData!=null){
            liveData.observe(this,locationString->{
                if(locationString!=null){
                    if(!sharedPreference.getBoolValue(SharedPreference.IS_FOLLOWING_ALERT)){
                        Gson gson=new Gson();
                        Type type=new TypeToken<Location>(){}.getType();
                        Location userLocation=gson.fromJson(locationString,type);
                        currentLocation=userLocation;
                    }else{
                        Gson gson=new Gson();
                        Type type=new TypeToken<VictimFollowingResponse>(){}.getType();
                        VictimFollowingResponse victimFollowingResponse=gson.fromJson(locationString,type);
                        List<Point> points=victimFollowingResponse.getPoints();
                        List<LatLng> latLngPoints=new ArrayList<>();
                        for(Point point:victimFollowingResponse.getPoints()){
                            latLngPoints.add(new LatLng(point.getLat(),point.getLong()));
                        }
                        int pointListSize=points.size();
                        if(pointListSize>0){
                            victimUser.setLatitude(points.get(pointListSize-1).getLat());
                            victimUser.setLongitude(points.get(pointListSize-1).getLong());
                        }
                        drawPolyLIne(latLngPoints);
                    }
                }
            });
        }
    }

是的,就是这样。

在这种情况下,即使在服务中设置后,实时数据也会在活动中不断返回 null。


我认为你的代码太复杂了。您可以简单地监听 SharedPreferences 的更改,使用registerOnSharedPreferenceChangeListener()侦听器,当您的应用程序打开时。

public class MyApplication extends Application {

    private static MyApplication singleton;
    public SharedPreferences preferences;

    public static MyApplication getInstance() {
        return singleton;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        singleton = this;
        preferences = PreferenceManager.getDefaultSharedPreferences(this);
        preferences.registerOnSharedPreferenceChangeListener(listener);
    }

    private SharedPreferences.OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            //do your code here
        }
    };

    public void unregisterListener() {
        preferences.unregisterOnSharedPreferenceChangeListener(listener);
    }
}

它覆盖了应用程序类,但您也可以在任何活动中使用它,但就像文档所说

注意:首选项管理器当前不存储对侦听器的强引用。您必须存储对侦听器的强引用,否则它将容易受到垃圾收集的影响。我们建议您在对象的实例数据中保留对侦听器的引用,只要您需要侦听器,该对象就会存在。

在我的示例中,您还应该覆盖清单文件中的应用程序标记

<application
    android:name=".MyApplication"
    >
</application>

请记住在退出应用程序之前在任何活动中取消注册侦听器

@Override
protected void onPause() {
    MyApplication.getInstance().unregisterListener();
    super.onPause();
}

如果您有自己的首选项文件,只需更改

preferences = PreferenceManager.getDefaultSharedPreferences(this);

to

preferences = getSharedPreferences("pref_filename", MODE_PRIVATE);

要访问该首选项,您不需要对其进行任何引用。您可以在任何您想要的活动中获取共享首选项文件的实例。这将会起作用,因为界面将侦听首选项文件中的任何更改。请注意,如果您传递的键与已包含的值相同,则侦听器不会将其识别为更改。所以,你可以改变 int 值,例如。从2到3,它会起作用,但从2到2不起作用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

观察 SharedPreferences 数据 的相关文章

  • SwingWorker 在 Unsafe.park() 处挂起

    我有一个SwingWorker与后台服务器通信 然后更新JFrame 我正在调试我的应用程序并注意到即使在SwingWorker完成了它的工作 它的线程仍然存在 它挂在Unsafe park java lang Object 这是一个本机方
  • 如何检测屏幕何时关闭?

    是否可以检测屏幕何时关闭并捕获它 我想在 Android 的全局设置中将计时器设置为 15 秒 我正在尝试查找一些如何捕获唤醒锁定模式的信息 只需注册您的应用程序即可执行操作Intent ACTION SCREEN OFF https de
  • 找不到模块:javafx.controls

    我已经下载了JavaFX SDK 解压它并设置PATH TO FX系统变量 如下本说明 https openjfx io openjfx docs install javafx 我使用了以下代码示例 import javafx applic
  • Apache POI 的 ProGuard 设置

    我正在构建一个使用 Apache POI 库的应用程序 当我调试应用程序 在不运行 Proguard 的情况下编译它 时 一切都运行良好 但是在导出 APK 后 当我运行应用程序并打开 Excel 文件时 出现以下异常 RuntimeExc
  • 为什么我无法解开根节点并反序列化对象数组?

    为什么我无法通过展开根节点来反序列化对象数组 import java io IOException import java util Arrays import java util List import org codehaus jack
  • 如何在Android Studio中关联.mp3文件

    我想根据列表视图项单击播放 mp3 文件 但是根据我的代码 我运行我的应用程序 出现此窗口 因此由于缺少音频选项 我真的不知道需要选择其中哪一个为了关联我的 mp3 文件 mainList setOnItemClickListener ne
  • 如何将 Facebook App 的 accessToken 添加到 GraphRequest.newGraphPathRequest 方法? [复制]

    这个问题在这里已经有答案了 我复制了下面的代码Facebook Graph Api console 但是 Android Studio 无法识别accessToken 我已经创建了一个Facebook App我得到了它acesstoken
  • android listactivity onCheckedChangeListener

    我正在开发一款应用程序 并且我有一个ListActivity 其选择模式设置为choice mode multiple 现在我想重写方法 当一项被调用时调用该方法选中 未选中 我发现onCheckChanged 方法仅针对RadioGrou
  • 用 Java 捕获扬声器输出

    使用Java可以捕获扬声器输出吗 此输出不是由我的程序生成的 而是由其他正在运行的应用程序生成的 这可以用 Java 完成还是我需要求助于 C C 我有一个基于 Java 的应用程序 使用过的爪哇声音 https stackoverflow
  • Handler、MessageQueue、Looper,它们都是运行在UI线程上的吗?

    我正在尝试解决线程问题 并且我知道我可能会使用Handler将消息 可运行对象发布到MessageQueue 这又被Looper并发送回Handler进行加工 如果我发帖到Handler在我的活动中 是Activity Handler Me
  • 有没有在android中使用roboguice和fragment的简单例子?

    我在寻找使用 Fragments RoboGuice 的工作示例时遇到问题 当您尝试使用 Android 片段事务管理器添加 删除片段时会出现此问题 一旦您告诉片段从 RoboFragment 继承 事务管理器就不再认为该类是片段 因为它扩
  • 使用 greenDao 动态查询

    我需要验证一些条件来创建完整的查询 QueryBuilder qb getMyObjDao queryBuilder if 某些条件 qb where MyObjDao Properties Prop1 eq someValue elseq
  • 将 Class 对象转换为字节

    如果我有一个Class http java sun com j2se 1 5 0 docs api java lang Class html在运行时实例 我可以获得它的 byte 表示形式吗 我感兴趣的字节将在类文件格式 http java
  • 在 Java Jersey 2 JAX-RS 中初始化单例

    我是泽西岛 2 22 2 的新手 请耐心等待 我正在创建一个与 LDAP 服务器交互的 REST 服务 用于存储 删除和检索用户数据 该服务通过执行加密 解密充当安全中介 在使用 REST 服务之前必须进行相当多的初始化 并且我只想执行此初
  • 如何避免连续“重置偏移量”和“寻找最新偏移量”?

    我正在尝试遵循本指南 https spark apache org docs latest structed streaming kafka integration html https spark apache org docs late
  • bean 中的 Spring JavaConfig 属性未设置?

    我正在考虑将 Spring JavaConfig 与一些属性文件一起使用 但 bean 中的属性未设置 bean 中的属性未设置 这是我的网络配置 Configuration EnableWebMvc PropertySource valu
  • 是否可以从 Android Studio 恢复被覆盖的文件?

    由于错误 我覆盖了我的两个来自 android studio 的具有相同名称的项目 并且今天我已经取消了该操作 我尝试打开主项目 但发现其中没有 Java 类 只有布局文件 在我覆盖的第二个项目中 文件存在巨大混乱 并尝试使用 Androi
  • 了解 FTS3/FTS4:什么是虚拟表并从中搜索具有可搜索的非虚拟表?

    阅读 SQLite3 的 FTS3 FTS4 文档的第一部分后 我现在感到非常困惑 我感到困惑的原因是散布在网络上的示例 我相信它没有涵盖所有可能的用例 另一个原因是我目前所处的情况 话虽如此 我有一个名为 Note 的表 其中包含两个类型
  • Ant 类路径和 junit.jar

    我有一个 build xml 它允许我运行 junit 测试 这是相关部分
  • 确保对象实现 Comparable

    我有一个小问题 想知道如何解决它 我有一个通用类Tuple

随机推荐

  • 我应该将费用/折扣列表合并到订单类别中还是将它们作为商品行

    我没有其他开发人员可以寻求建议或 你觉得怎么样 我在想this 所以 如果您有时间 请阅读并告诉我您的想法 显示比描述更容易 但该应用程序本质上就像一个销售点应用程序 由 3 个主要部分组成 商品 订单商品和订单 项目类是来自数据存储区的数
  • 使用行号更新 Oracle 表列

    我想用行号更新表列 中的每一行empid列应使用相关行号进行更新 我尝试了以下查询 UPDATE employee SET empid row number 但这是行不通的 任何想法 首先 这不是正确的语法row number 功能 因为你
  • sql server单行多列合并为一列

    我有这样的桌子 Reg No Student Name Subject1 Subject2 Subject3 Subject4 Total 101 Kevin 85 94 78 90 347 102 Andy 75 88 91 78 332
  • C# 中的分号

    为什么 C 中每行末尾都需要分号 为什么编译器不能知道每一行的结束位置 行终止符将使您能够将语句分成多行 另一方面 像 VB 这样的语言有一个行继续符 并且可能会引发分号的编译错误 我个人认为用分号终止语句比继续使用下划线要干净得多 最后
  • SilverStripe 3 - <%循环%>的选项

    是否有我可以添加到循环中的所有选项的列表 我不知道选项是否是正确的名称 我的意思是这些 有人可以告诉我这里可能发生的一切吗 它的正确名称是什么 你的问题有一个错误 是 or 看 您正在循环 DataObject 列表 well loop基本
  • 为什么比较 constexpr 函数的两个参数不是静态断言的常量条件?

    constexpr uint32 t BitPositionToMask int i int Size static assert i lt Size bit position out of range return 1 lt lt i 这
  • kubectl 端口转发失败

    我正在裸机 RHEL7 上运行 k8s 集群 我正在尝试运行 kubectl port forward 命令并收到错误 kubectl port forward p somepod 10000 8080 I0128 15 33 33 802
  • 从 powershell 调用 vcvarsall.bat 后运行构建脚本

    我正在尝试运行 Visual Studio 开发人员 cmd 提示符 环境变量设置批处理文件 然后运行 Powershell 脚本中的构建脚本 如下所示 cmd v on k C Program Files x86 Microsoft Vi
  • RSpec 测试 PUT 更新操作

    我正在尝试编写一些 RSpec 测试来测试我的应用程序 但我偶然发现了几个问题 但我找不到任何解决方案 1 我正在尝试测试更新操作 这是我的代码 it email is a new one do put update id user use
  • HttpApplicationState 在 MVC 控制器中不可用

    我正在使用 MVC2 和 VS2010 开发一个网站 需要使用应用程序状态全局值 我可以设置一个像 Application hits 0 这样的值在 Global asax 中 但是当尝试在 MVC 控制器中使用相同的内容时 总是会出现以下
  • 为什么我们*应该*使用EventHandler

    我讨厌事件处理程序 我讨厌我必须投sender如果我想用它做任何事 我讨厌我必须创建一个继承自的新类EventArgs to use EventHandler
  • 零填充 numpy 数组

    在末尾用零填充数组的更Pythonic的方法是什么 def pad A length A np array 1 2 3 4 5 pad A 8 expected 1 2 3 4 5 0 0 0 在我的实际用例中 事实上我想将数组填充到最接近
  • facet_wrap 添加 geom_hline

    我的 ggplot 代码如下 facet wrap 函数在页面上为每个名称绘制 20 个图 并且沿 x 轴有 5 个 Pcode 我想计算每个名称的平均 TE Contr 并将该值绘制为每个图上的水平线 由 Facet wrap 分割 目前
  • Java Swing 按钮颜色[重复]

    这个问题在这里已经有答案了 我正在使用 NET Beans IDE 在 LINUX 中开发我的应用程序 我使用 Syntheta 包来生成新的外观和感觉 到目前为止一切都很好 现在 我的下一阶段是在某些数据库状态发生变化时为按钮添加颜色 例
  • MySQL 中的数字序列

    在Python中 如果我想要一个从0到9 含 的序列 我会使用 xrange 0 10 有什么办法可以在 MySQL 中做到这一点吗 由于不存在 xrange 这样的东西 因此可以使用一个单独的表来存储整数 如前所述 或者只是创建一个存储过
  • 如何将 Instagram feed 嵌入我的网站 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在尝试将客户端的 Instagram feed 集成到网站侧边栏 我的网站堆栈是 Bootstrap Vanilla JS Jqu
  • mysql 外键约束格式不正确错误

    我有两张桌子 table1是带有列的父表ID and table2有一个柱子IDFromTable1 不是真实的名字 当我戴上FK时IDFromTable1 to ID in table1我收到错误Foreign key constrain
  • Neo4j 非托管扩展和 GuardTimeoutException

    我非常需要一些关于我在 Java 中构建的 Neo4j 非托管扩展时遇到的问题的建议 我创建了一个非常简单的代码示例来突出我的问题 基本前提是我想设置 org neo4j server webserver limit executionti
  • 为什么大多数 JavaScript 原生函数都比它们的原始实现慢?

    我注意到了some http jsperf com map native vs implemented tests http jsperf com concat tests blabla原生 JavaScript 函数通常比简单的实现慢得多
  • 观察 SharedPreferences 数据

    我正在尝试观察共享偏好中的数据变化 我找到了这个similar https stackoverflow com questions 50649014 livedata with shared preferences问题回答者 SimplyP