我正在尝试观察共享首选项中的数据更改。我发现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。
答案 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将不起作用。