Как вызвать функцию * после * onPreferenceChange?

#android

#Android

Вопрос:

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

Это мой текущий код:

 mypref.setOnPreferenceChangeListener(
   new OnPreferenceChangeListener() {
      public boolean onPreferenceChange(Preference arg0, Object arg1) {
         if(arg1.toString().matches("...") == false) {
            ...
            return false;
         }

         ...

         updateVariables();
         return true;
     }
});
  

Проблема в том, что при updateVariables() вызове значение предпочтения еще не обновляется, и функция видит старое значение.

 private void updateVariables()
{
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
    Map<String, ?> savedKeys = sharedPref.getAll();

    for (Map.Entry<String, ?> entry : savedKeys.entrySet()) {
       // for each preference...
    }
}
  

Каким было бы наименее инвазивное решение? Спасибо!

Ответ №1:

Второй аргумент onPreferenceChange() ( arg1 здесь) — это новое значение. Я бы предложил просто добавить это updateVariables() в качестве аргумента и просто передать объект для работы с ним.

Комментарии:

1. Спасибо. Но что, если updateVariables() мне нужно повторить множество других настроек? Мне понадобится много разных аргументов.

2. Это здесь просто дает вам одно значение предпочтения, которое изменилось. Все остальные такие же, пока не будет возвращен обратный вызов. Итак, вам просто нужно переслать один, все остальные можно прочитать, создав обычный SharedPreferences объект. (Кроме того, вы все равно можете использовать a List в качестве аргумента, если у вас есть много аргументов для приведения)

3. хм … может быть, я делаю это неправильно, но я добавил пример updateVariables() . Как я могу выполнить цикл, если я добавлю дополнительный аргумент с обновленным значением? Как я могу избежать обработки одного и того же предпочтения 2 раза (один раз со старым значением из SharedPreferences, один раз с новым значением из аргументов)? Я могу думать только о грязных решениях: S

4. Я не уверен, правильно ли я понял это, но вы можете просто перенаправить ключ и значение в метод и удалить существующий ключ из map / set . После этого добавьте новую с новым значением. Затем выполните цикл. (хотя я не понимаю, почему вы должны перебирать все настройки при изменении одного из них. Мне это кажется несколько неэффективным, но, возможно, я просто не знаю контекста)

5. Отлично, это хорошее решение 🙂 Да, я пытался избежать итерации… но я не смог найти альтернативные способы сделать то, что мне нужно, без большого грубого цикла. Может быть, это потому, что я еще не знаю всех странных деталей этой странной и блестящей платформы Android: D

Ответ №2:

Я только нашел уловку, чтобы немного поспать, а затем позвонить, чтобы действительно обновить.

 private void updateVariables() {

    new Thread() {
        public void run() {
            try {
               Thread.sleep(100); //Sleep a little bit to let Android update the Preference
            } catch (InterruptedException e) {
            }
            //Now go back to the main UI:
            getActivity().runOnUiThread
                    (new Runnable() {
                         @Override
                         public void run() {
                             //
                             //Here you do the update of your screen
                             //
                         }
                     }
                    );
        }
    }.start();

}
  

Ответ №3:

Использование PreferenceFragmentCompat

 public class FragmentSettings
extends PreferenceFragmentCompat
implements SharedPreferences.OnSharedPreferenceChangeListener


@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {

    addPreferencesFromResource(R.xml.app_preferences);

    getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}


@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {

    switch(key)
    {
        case "KEY1":
            // DO STUFF
            break;

        case "KEY2":
            // DO STUFF
            break;
    }
}