观察SharedPreferences数据 [英] Observing SharedPreferences Data

查看:57
本文介绍了观察SharedPreferences数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试观察共享首选项中的数据更改.我发现此类似问题由

I am trying to observe data changes in shared preferences. I found this similar question answered by @SimplyProgrammerand followed the steps that he directed and at the end of the day my observer was still not working.

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

Then I decided to seek some assistance to better understand why.

这是我的实现方式

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

I started by implementing the abstract live data

    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();
    }
}

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

I then implemented the live data type class

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);
    }
}

然后我像这样将其添加到我的首选项"管理类中

I then added this to my Preference management class like so

实例化和设置吸气剂

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);
    }

然后在我的活动中,我像这样访问sharedPreferenceLiveData

then in my activity, I access sharedPreferenceLiveData like this

    @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.

in this case, the live data keeps returning null in the activity even after being set in a service.

推荐答案

我认为您的代码太复杂了.打开应用程序后,您可以使用registerOnSharedPreferenceChangeListener()侦听器来侦听SharedPreferences的更改.

I think that your code is too complicated. You can simply listen for SharedPreferences changes, using registerOnSharedPreferenceChangeListener() listener, when your app is turned on.

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);
    }
}

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

It overrides an application class, but you can also use this in any activity, but like docs say

警告:首选项管理器当前不存储对侦听器的强引用.您必须存储对侦听器的强引用,否则将很容易受到垃圾回收的影响.我们建议您在需要侦听器的对象的实例数据中保留对侦听器的引用.

Caution: The preference manager does not currently store a strong reference to the listener. You must store a strong reference to the listener, or it will be susceptible to garbage collection. We recommend you keep a reference to the listener in the instance data of an object that will exist as long as you need the listener.

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

In my example, you should also override an application tag in manifest file

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

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

And remember to unregister listener in any activity, before you'll exit an app

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

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

If you have your own preference file, just change

preferences = PreferenceManager.getDefaultSharedPreferences(this);

preferences = getSharedPreferences("pref_filename", MODE_PRIVATE);

要访问该首选项,您无需对其进行任何引用.您可以在任何所需的活动中获取sharedpreferences文件的实例.那将是可行的,因为接口将侦听首选项文件中的任何更改.请注意,如果您传递的键具有与已包含的值相同的值,则侦听器不会将其识别为更改.因此,您可以更改int值,例如.从2到3,它将起作用,但从2到2将不起作用.

To access that preferences, you no need any reference to it. You can get instance of sharedpreferences file in any activity you want. That will be work, because interface will listen for any changes in preferences file. Note that, if you'll pass a key with the same value which is already contained, listener doesn't recognize that as change. So, you can change int value eg. from 2 to 3, and it will work, but from 2 to 2 won't work.

这篇关于观察SharedPreferences数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆