J'ai défini une instance de SharedPreferences
utilisée en mode multi-processus.
public class Prefs {
private static SharedPreferences prefs;
private static SharedPreferences.Editor editor;
private static void init(Context context) {
prefs = context.getSharedPreferences("alaki",
Context.MODE_MULTI_PROCESS);
editor = prefs.edit();
}
// static methods to set and get preferences
}
Maintenant, j'utilise cette classe sur un service avec un processus séparé et également dans mon processus d'application principal de manière statique.
Tout va bien, mais parfois toutes les données stockées sur l'instance SharedPreferences sont supprimées!
Comment puis-je résoudre ce problème?
Edit: Enfin, j'ai résolu mon problème en utilisant IPC.
Il n’existe actuellement aucun moyen d’accéder en toute sécurité à SharedPreferences
sur plusieurs processus, comme indiqué dans sa documentation .
Remarque: Cette classe ne prend pas en charge l'utilisation sur plusieurs processus.
Après avoir beaucoup testé avec MODE_MULTI_PROCESS
, j'ai trois essais à partager:
1- Initialise la SharedPreferences
une fois dans chaque processus et l'utilise plusieurs fois.
Le problème: Les valeurs ne sont pas reflétées dans chaque processus comme prévu. Ainsi, chaque processus a sa propre valeur de SharedPreferences.
2- Initialise la SharedPreferences
dans chaque put ou get.
Cela fonctionne réellement et la valeur est maintenant interchangeable entre les processus.
Le problème: parfois après avoir accédé agressivement à sharedpref, le fichier de préférences partagées a été supprimé avec tout son contenu, comme décrit dans ce issue , et cet avertissement apparaît dans le bûche:
W/FileUtils﹕ Failed to chmod(/data/data/com.hegazy.multiprocesssharedpref/shared_prefs/myprefs.xml): Android.system.ErrnoException: chmod failed: ENOENT (No such file or directory)
Vous pouvez trouver pourquoi cela se produit dans le numéro.
3- Utilisez la synchronisation pour verrouiller les méthodes qui mettent et obtiennent des valeurs dans la variable SharedPreferences
.
C'est complètement faux. la synchronisation ne fonctionne pas entre les processus. La SharedPreferences
utilise effectivement la synchronisation dans son implémentation, mais cela ne fait que garantir la sécurité des threads, pas la sécurité des processus. Ceci est très bien décrit ici .
SharedPreferences en soi n'est pas sûr pour le processus. C'est probablement pourquoi Documentation SharedPreferences dit
Remarque: actuellement, cette classe ne prend pas en charge l'utilisation sur plusieurs processus. Ce sera ajouté plus tard.
L'utilisation de la méthode commit()
enregistre les modifications dans le stockage persistant. Par conséquent, il est lent et crée des conflits entre plusieurs appels provenant d'autres processus.
Cependant, il existe une alternative à cette méthode. Vous devez appeler la méthode apply()
. Cette méthode stocke les modifications en mémoire, puis dans le stockage sur disque de manière asynchrone, ce qui la rend plus fiable.
J'ai travaillé autour de cela en combinant:
SharedPreferences
(par exemple, en utilisant un mécanisme de verrouillage basé sur une socket )SharedPreferences
avec l'indicateur MODE_MULTI_PROCESS
chaque fois que vous voulez l'utiliser pour contourner la mise en cache en mémoireCela semble fonctionner correctement, mais cela n’a pas été complètement testé dans le monde réel, donc je ne sais pas s’il est parfaitement fiable.
Vous pouvez voir un exemple de travail que j'ai écrit ici .
Avertissement : On dirait que MODE_MULTI_PROCESS
est obsolète dans Android M. Il pourrait ne plus fonctionner dans le futur.
rappelle que l'utilisation d'objets de contexte en tant que champ statique entraîne un risque de fuite du contexte, car elle ne déclare pas l'objet dans la classe d'application
public class CustomApplication extends Application{
private Prefs prefs;
public void onCreate(){
prefs = new Prefs(this);
}
public Prefs getPrefs(){
return prefs;
}
}
De n'importe quel contexte, vous pouvez obtenir les préfs
((MyApplication)context.getApplicationContext()).getPrefs();
Utilisez un fournisseur de contenu utilisant SharedPreferences. Exemple, voir ici: https://github.com/hamsterksu/MultiprocessPreferences