观察SharedPreferences数据

时间:2020-02-26 09:43:05

标签: 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);
    }
}

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

实例化和设置吸气剂

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

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

1 个答案:

答案 0 :(得分:6)

我认为您的代码太复杂了。打开应用程序后,您可以使用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);
    }
}

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

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

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

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

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

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

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

preferences = PreferenceManager.getDefaultSharedPreferences(this);

preferences = getSharedPreferences("pref_filename", MODE_PRIVATE);

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