java - 观察 SharedPreferences 数据

标签 java android sharedpreferences rx-java android-livedata

我正在尝试观察共享偏好中的数据变化。我找到了这个similar问题由 @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);
    }
}

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

实例化和设置 setter/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);
    }

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

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

是的,就是这样。

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

最佳答案

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

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

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

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.

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

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

并记住在退出应用程序之前在任何 Activity 中取消注册监听器

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

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

preferences = PreferenceManager.getDefaultSharedPreferences(this);

preferences = getSharedPreferences("pref_filename", MODE_PRIVATE);

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

关于java - 观察 SharedPreferences 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60410906/

相关文章:

java - 如何使用 JDBC Appender 将错误日志保存到数据库中

java - CloudSolrClient 线程安全吗?

Java 处理数十亿字节

Android某些按钮在横向时不显示

java - 解析数组值的查询

android - 何时首次创建共享首选项文件?

java - 自动选择项目

android OAuth 问题,如何发送请求 token 请求

android - 我可以安全地更改 SharedPreferences 变量的类型吗?

c# - 在 xamarin 中使用共享首选项