Ich habe onSharedPreferenceChanged
in meiner Hauptaktivität implementiert .
Wenn ich die Einstellungen in der Hauptaktivität ändere, wird mein Ereignis ausgelöst.
Wenn ich die Einstellungen über meinen PreferenceActivity
Einstellungsbildschirm ändere ( ), wird mein Ereignis NICHT ausgelöst, wenn Einstellungen geändert werden (da es sich um eine separate Aktivität und einen separaten Verweis auf sharedPreferences handelt?).
Hat jemand eine Empfehlung, wie ich diese Situation überwinden soll?
Vielen Dank!
EDIT1: Ich habe versucht, den Ereignishandler direkt in meiner Präferenzaktivität hinzuzufügen, aber er wird nie ausgelöst. Die folgende Methode wird während onCreate meiner Präferenzaktivität aufgerufen. Wenn ich Werte ändere, wird die Nachricht nie gedruckt ( msg()
ist ein Wrapper für Log.d
).
private void registerChangeListener () {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
sp.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener () {
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
msg (" ***** Shared Preference Update ***** ");
Intent i = new Intent();
i.putExtra("KEY", key);
i.setAction("com.gtosoft.dash.settingschanged");
sendBroadcast(i);
// TODO: fire off the event
}
});
}
quelle
Antworten:
Der
OnSharedPreferenceChangeListener
Müll wird in Ihrem Fall gesammelt, wenn Sie eine anonyme Klasse verwenden.Um dieses Problem zu lösen, verwenden Sie den folgenden Code
PreferenceActivity
, um einen Änderungslistener zu registrieren und die Registrierung aufzuheben:public class MyActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener { @Override protected void onResume() { super.onResume(); // Set up a listener whenever a key changes getPreferenceScreen().getSharedPreferences() .registerOnSharedPreferenceChangeListener(this); } @Override protected void onPause() { super.onPause(); // Unregister the listener whenever a key changes getPreferenceScreen().getSharedPreferences() .unregisterOnSharedPreferenceChangeListener(this); } public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,String key) { // do stuff }
Beachten Sie außerdem, dass der Listener nur aufgerufen wird, wenn sich der tatsächliche Wert ändert. Wenn Sie denselben Wert erneut einstellen, wird der Listener nicht ausgelöst.
Siehe auch SharedPreferences.onSharedPreferenceChangeListener wird nicht konsistent aufgerufen
quelle
Dies geschieht, weil Müllsammler. es funktioniert nur einmal. dann wird die Referenz als Müll gesammelt. Erstellen Sie also ein Instanzfeld für den Listener.
private OnSharedPreferenceChangeListener listner; listner = new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { //implementation goes here } }; prefs.registerOnSharedPreferenceChangeListener(listner);
quelle
Ich bin hier angekommen, wie viele andere auch, weil mein Zuhörer nicht gefeuert wird, wenn ich meinen Booleschen Wert von
true
infalse
oder umgekehrt ändere.Nach vielem Lesen und Umgestalten, Umschalten
contexts/inner
classes/privates/static/
und dergleichen erkannte ich meinen (dummen) Fehler:Das
onSharedPreferenceChanged
wird nur aufgerufen, wenn sich etwas ändert. Nur. Je.Während meiner Tests war ich so dumm, die ganze Zeit auf dieselbe Schaltfläche zu klicken, sodass der Präferenz immer derselbe Boolesche Wert zugewiesen wurde, sodass er sich nie änderte.
Hoffe das hilft jemandem !!
quelle
Eine andere Möglichkeit, das Problem zu vermeiden, besteht darin, Ihre Aktivität zur Listener-Klasse zu machen. Da es nur eine Überschreibungsmethode mit einem eindeutigen Namen gibt, können Sie dies tun:
public class MainActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sharedPreferences.registerOnSharedPreferenceChangeListener(this); ... } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { ... } }
quelle
Beachten Sie, dass in der ursprünglichen Frage von einer MainActivity gesprochen wurde, die Änderungen in einer PreferenceActivity abhört. Der Fragesteller fügte dann ein "EDIT1" hinzu und änderte die Frage so, dass sie in der PreferenceActivity selbst abgehört wurde. Das ist einfacher als das erstere und scheint das zu sein, was alle Antworten annehmen. Aber was ist, wenn Sie immer noch das frühere Szenario wollen?
Nun, es wird auch funktionieren, aber verwenden Sie OnResume () und OnPause () nicht, um den Listener zu registrieren und die Registrierung aufzuheben. Dies führt dazu, dass der Listener ineffektiv ist, da der Benutzer die MainActivity verlässt, wenn er die PreferenceActivity verwendet (was sinnvoll ist, wenn Sie darüber nachdenken). Es wird also funktionieren, aber dann hört Ihre MainActivity auch dann im Hintergrund zu, wenn der Benutzer sie nicht verwendet. Eine Art Verschwendung von Ressourcen, nicht wahr? Es gibt also eine andere Lösung, die zu funktionieren scheint. Fügen Sie einfach eine Methode zu OnResume () hinzu, um alle Einstellungen erneut zu lesen. Wenn ein Benutzer die Bearbeitungseinstellungen in einer PreferenceActivity abgeschlossen hat, nimmt die MainActivity diese auf, wenn der Benutzer zu ihr zurückkehrt und Sie überhaupt keinen Listener benötigen .
Jemand, bitte lassen Sie mich wissen, wenn er ein Problem mit diesem Ansatz sieht.
quelle
Warum fügen Sie
onSharedPreferenceChanged
in den restlichen Aktivitäten nicht einfach ein hinzu, bei dem sich die Einstellungen ändern könnten?quelle
Der Garbage Collector löscht, dass ... Sie stattdessen einen Anwendungskontext verwenden sollten ... oder einfach den Code hinzufügen, wenn die App gestartet wird ... und dann den Listener mit dem Anwendungskontext hinzufügen ...
quelle
Ziehen Sie in Betracht, PreferencesChangeListener in der Instanz der Android App- Klasse zu belassen. Obwohl es sich NICHT um eine saubere Lösung handelt, sollte das Speichern von Referenzen in der App verhindern, dass GC Ihren Listener mit Müll sammelt, und Sie sollten weiterhin in der Lage sein, DB-Änderungsaktualisierungen zu erhalten. Denken Sie daran, dass der Präferenzmanager keinen starken Verweis auf den Hörer speichert! ( WeakHashMap )
/** * Main application class */ class MyApp : Application(), KoinComponent { var preferenceManager: SharedPreferences? = null var prefChangeListener: MySharedPrefChangeListener? = null override fun onCreate() { super.onCreate() preferenceManager = PreferenceManager.getDefaultSharedPreferences(this) prefChangeListener = MySharedPrefChangeListener() preferenceManager?.registerOnSharedPreferenceChangeListener(prefChangeListener) } }
und
class MySharedPrefChangeListener : SharedPreferences.OnSharedPreferenceChangeListener { /** * Called when a shared preference is changed, added, or removed. */ override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { if (sharedPreferences == null) return if (sharedPreferences.contains(key)) { // action to perform } } }
quelle
Beim Lesen von Word-lesbaren Daten, die von der ersten App gemeinsam genutzt werden, sollten wir dies tun
Ersetzen
getSharedPreferences("PREF_NAME", Context.MODE_PRIVATE);
mit
getSharedPreferences("PREF_NAME", Context.MODE_MULTI_PROCESS);
in der zweiten App, um den aktualisierten Wert in der zweiten App zu erhalten.
quelle
SharedPreferences
von mehreren Prozessen nicht. Dies führt zu Parallelitätsproblemen, die dazu führen können, dass alle Einstellungen verloren gehen. Wird auchMODE_MULTI_PROCESS
nicht mehr unterstützt.