onSharedPreferenceChanged pas tiré si le changement se produit dans une activité séparée?
-
05-10-2019 - |
Question
Je l'ai mis en œuvre onSharedPreferenceChanged
dans mon activité principale.
Si je change les préférences de l'activité principale, mes feux de l'événement.
Si je change les préférences à travers mon écran Préférences (PreferenceActivity
) mon événement ne se déclenche pas lorsque les préférences sont modifiées (parce qu'il est une activité distincte et séparée pour référence sharedPreferences?)
Quelqu'un at-il une recommandation de la façon dont je devrais aller sur le dépassement de cette situation?
Merci!
EDIT1: J'ai essayé d'ajouter le gestionnaire d'événement dans mon activité de préférence mais il n'a jamais incendies. La méthode suivante est appelée pendant onCreate de mon activité de préférence. Quand je change les valeurs, il n'imprime le message (msg()
est une enveloppe pour 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
}
});
}
La solution
Le OnSharedPreferenceChangeListener
reçoit les déchets collectés dans votre cas si vous utilisez une classe anonyme.
Pour résoudre ce problème utilisation le code suivant dans PreferenceActivity
d'enregistrer et désenregistrer un écouteur de changement:
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
}
De plus il faut savoir que l'auditeur ne s'appelle si la valeur réelle change. Réglage de la même valeur à nouveau ne se déclenche pas l'auditeur.
voir aussi SharedPreferences.onSharedPreferenceChangeListener pas appelé constamment
Autres conseils
Cela arrive parce que garbage collector. ses œuvres qu'une seule fois. alors la référence est avec les déchets ménagers. afin de créer champ d'instance pour l'auditeur.
private OnSharedPreferenceChangeListener listner;
listner = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
//implementation goes here
}
};
prefs.registerOnSharedPreferenceChangeListener(listner);
Je suis arrivé ici, comme beaucoup d'autres, parce que mon auditeur ne sera pas déclenché lorsque j'ai changé booléen de true
à false
, ou vice-versa.
Après avoir beaucoup lu, et refactoring, commutation contexts/inner
de classes/privates/static/
et autres, je me suis rendu mon (stupide) Erreur:
Le onSharedPreferenceChanged
est uniquement appelé si quelque chose change. Seulement. Jamais.
Au cours de mes tests, j'étais tellement stupide de cliquer sur le même bouton tout le temps, attribuant ainsi la même valeur booléenne à la préférence tout le temps, il n'a jamais changé.
Hope this helps quelqu'un !!
Une autre façon d'éviter le problème est de rendre votre activité la classe auditeur. Comme il n'y a qu'une seule méthode de remplacement avec un nom distinctif que vous pouvez faire ceci:
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)
{
...
}
}
Notez que la question initiale a parlé d'une MainActivity écoute de changements de réglage dans un PreferenceActivity. Le demandeur a ensuite ajouté un « EDIT1 » et a changé la question à l'écoute dans le PreferenceActivity lui-même. C'est plus facile que l'ancien et semble être ce que toutes les réponses supposent. Mais si vous voulez encore l'ancien scénario?
Eh bien, cela fonctionnera aussi, mais ne pas utiliser onResume () et OnPause () pour enregistrer et désenregistrer l'auditeur. Cela provoquera l'auditeur d'être sans effet parce que les feuilles de l'utilisateur du MainActivity lorsqu'ils utilisent le PreferenceActivity (ce qui est logique quand on y pense). Donc, cela va fonctionner, mais votre MainActivity sera toujours à l'écoute en arrière-plan, même lorsque l'utilisateur ne l'utilise pas. Une sorte de gaspillage de ressources non? Donc, il y a une autre solution qui semble fonctionner, il suffit d'ajouter une méthode pour onResume () relise toutes les préférences. De cette façon, lorsqu'un utilisateur se termine l'édition des préférences dans un PreferenceActivity, les MainActivity vont les ramasser quand l'utilisateur revient à vous et ne pas besoin d'un auditeur à tous .
Quelqu'un s'il vous plaît laissez-moi savoir s'ils voient un problème avec cette approche.
Pourquoi ne pas ajouter juste un onSharedPreferenceChanged
dans le reste des activités où les préférences pourraient changer?
Le garbage collector efface ... que vous devriez envisager d'utiliser un contexte d'application à la place ... ou tout simplement ajouter le code lorsque app catapultes ... puis ajoutez le l'auditeur avec le contexte de l'application ...
Considérez maintenant PreferencesChangeListener dans Android App instance de classe. Bien qu'il soit pas une référence solution de stockage propre à l'intérieur App devrait arrêter GC de déchets collecte de votre écoute et vous devriez toujours être en mesure de recevoir des mises à jour de changement DB. Rappelez-vous que gestionnaire de préférence ne pas enregistrer une forte référence à l'auditeur! ( 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)
}
}
et
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
}
}
}
Lors de la lecture de mots données lisibles partagées par la première application, nous devrions
Remplacer
getSharedPreferences("PREF_NAME", Context.MODE_PRIVATE);
avec
getSharedPreferences("PREF_NAME", Context.MODE_MULTI_PROCESS);
dans la deuxième application pour obtenir la valeur mise à jour dans la deuxième application.