【问题标题】:Observing SharedPreferences Data观察 SharedPreferences 数据
【发布时间】:2020-06-10 03:33:48
【问题描述】:

我正在尝试观察共享偏好中的数据变化。我发现@SimplyProgrammer 回答了这个similar 问题,并按照他指示的步骤进行操作,最终我的观察员仍然无法工作。

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

这是我的实现

我从实现抽象的实时数据开始

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

然后在我的活动中,我像这样访问 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。

【问题讨论】:

  • 请在下面的链接中找到简单的解决方案。 stackoverflow.com/a/63500084/7176189
  • 感谢@Jai,我已经设法使用异步任务解决了这个问题,但现在使用协程我已经在考虑迁移我的代码了..

标签: java android sharedpreferences rx-java android-livedata


【解决方案1】:

我认为您的代码太复杂了。当您的应用打开时,您可以使用 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 就不行了。

【讨论】:

  • 谢谢,@grabarz121 我将如何传递数据 ama 监听的密钥...
  • 我也确实有一个独立的首选项管理器类,我还必须实现这一行吗preferences = PreferenceManager.getDefaultSharedPreferences(this);
  • 有 kotlin 版本吗?
猜你喜欢
  • 2019-06-04
  • 2014-01-28
  • 2019-03-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-31
  • 1970-01-01
  • 1970-01-01
  • 2012-02-22
相关资源
最近更新 更多