Подтвердить что ты не робот

Использование SharedPreferences в многопроцессном режиме

Я определил экземпляр SharedPreferences, который используется в многопроцессном режиме.

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
}

Теперь я использую этот класс для службы с отдельным процессом, а также в моем основном процессе приложения статическим способом.
Все идет хорошо, но иногда удаляются все сохраненные данные на экземпляре SharedPreferences!
Как я могу решить эту проблему?

Изменить: Наконец, я решил проблему с помощью IPC.

4b9b3361

Ответ 1

В настоящее время нет способа безопасного доступа к SharedPreferences для нескольких процессов, как описано в документации.

Примечание. Этот класс не поддерживает использование нескольких процессов.

После многого тестирования с помощью MODE_MULTI_PROCESS у меня есть три испытания:

1- Инициализируйте SharedPreferences один раз в каждом процессе и используйте его несколько раз.

Проблема: Значения не отражаются в каждом процессе, как ожидалось. Таким образом, каждый процесс имеет собственное значение SharedPreferences.

2- Инициализировать SharedPreferences в каждом столбце put или get.

Это действительно работает, и теперь значение становится взаимозаменяемым между процессами.

Проблема: иногда после активного доступа к sharedpref файл общих предпочтений удалялся со всем его содержимым, как описано в этом проблема, и я получаю это предупреждение в журнале:

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)

Вы можете узнать, почему это происходит в этой проблеме.

3- Используйте синхронизацию для блокировки методов, которые помещают и получают значения в SharedPreferences.

Это совершенно неправильно; синхронизация не работает в разных процессах. SharedPreferences фактически использует синхронизацию в своей реализации, но только обеспечивает безопасность потоков, а не безопасность процесса. Это описано очень хорошо здесь.

Ответ 2

Собственные файлы SharedPreferences не являются безопасными для процесса. Вероятно, поэтому Документация SharedPreferences говорит

Примечание. В настоящее время этот класс не поддерживает использование нескольких процессов. Это будет добавлено позже.

Ответ 3

С помощью метода commit() сохраняются изменения в постоянном хранилище, поэтому он медленный и конфликтует с несколькими вызовами из других процессов.

Однако существует альтернатива этому методу, вы должны вызвать метод apply(), этот метод сохраняет изменения в памяти, а затем на дисковой памяти асинхронно, поэтому он более надежный.

Ответ 4

Я работал над этим, комбинируя:

  • Предоставление каждому процессу взаимоисключающего доступа к файлу SharedPreferences (например, с помощью механизма блокировки на основе сокетов)
  • Повторно инициализировать SharedPreferences с помощью флага MODE_MULTI_PROCESS каждый раз, когда вы хотите использовать его для обхода кэширования в памяти

Кажется, что это работает нормально, но он не был полностью протестирован в реальном мире, поэтому я не знаю, насколько он надежен.

Вы можете увидеть рабочий пример, который я написал здесь.

Предупреждение. Похоже, MODE_MULTI_PROCESS устарел в Android M. Он может перестать работать в будущем.

Ответ 5

напоминает, что использование контекстных объектов как статического поля, у вас есть риск утечки контекста, потому что не объявлять объект в классе приложения

public class CustomApplication extends Application{
     private Prefs prefs;

     public void onCreate(){
          prefs = new Prefs(this);
     }

     public Prefs getPrefs(){
        return prefs;
     }
}

Из любого контекста вы можете получить префы

   ((MyApplication)context.getApplicationContext()).getPrefs();

Ответ 7

Если два процесса записывают данные в SharedPreferences, возможно, все значения SharedPreferences будут reset равными значениям по умолчанию.

Также вы можете попробовать вызвать clear() в редакторе перед сохранением val

SharedPreferences.Editor sp = settings.edit();
sp.clear();
sp.putString("Name", "YourName");
sp.commit();