Android – общие настройки, установленные в AsyncTask onPostExecute (), не всегда установлены?

У меня есть код, который работает 98% времени и 100% во время моего собственного тестирования, поэтому я не могу воспроизвести проблему, отличную от того, как пользовательские устройства испытывают эту проблему.

То, что я делаю в onPostExecute (), задает такой параметр:

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( AddProblemActivity.this); prefs.edit().putString("recent_problem_id", result ).commit(); 

А затем перейдите к следующему действию:

  Intent myIntent = new Intent(AddProblemActivity.this, ProblemActivity.class); AddProblemActivity.this.startActivity(myIntent); 

А затем попытайтесь получить такой параметр:

 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( ProblemActivity.this); // display a loading message before problem loads. String recent_problem_id = prefs.getString( "recent_problem_id" , null ); if ( recent_problem_id == null ) { // Sometimes it is null! } 

Кто-нибудь знает, почему это происходит?

Благодаря!

Если вы пытаетесь передать данные в новое действие, почему бы не добавить его как строку в намерении? Затем получите эту строку из намерения в новом действии. Если вам все равно нужно сохранить его, вы можете сделать это в onCreate () новой активности после того, как он вытащит его из намерения.

 Intent myIntent = new Intent(AddProblemActivity.this, ProblemActivity.class); //Add results here myIntent.putExtra("RecentProblemId", result); AddProblemActivity.this.startActivity(myIntent); 

Затем в onCreate вашей новой активности выполните:

 String recentProblemId = getIntent().getStringExtra("RecentProblemId"); 

Теперь, если вам все еще нужна эта информация, выполните следующие действия:

 if(recentProblemId != null){ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( ProblemActivity.this); prefs.putString("recent_problem_id",recentProblemId).commit(); } 

Я знаю, что это точно не отвечает на ваш вопрос о том, почему строка не всегда привязана к предпочтениям в onPostExecute (). Однако наилучшей практикой передачи информации между мероприятиями является намерение и дополнительные услуги.

Мое предположение о том, почему это может не всегда работать для некоторых пользователей, заключается в том, что их устройства не записывают данные в файл общих предпочтений до того, как начнется новое действие, и попытается прочитать из этого же файла. Надеюсь это поможет.

Прежде всего, см. Ответ Рагхава Сауда.
Есть один деликатный момент. Вы можете начать выполнять свою AsyncTask, чем вращать устройство. Активность будет воссоздана, а в PostExecute у вас будет неправильный контекст, чтобы ваши настройки не сохранялись.
Если это правда, вы должны использовать onRetainNonConfigurationInstance (), чтобы сохранить экземпляр соответствующей задачи.

Я не уверен в этом, но я думаю, что проблема может быть связана с различием в Контексте, который вы передаете. AddProblemActivity вы используете контекст AddProblemActivity , а затем контекст ProblemActivity . Попробуйте использовать заданное предпочтение, например, имя файла:

 SharedPreferences prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE); 

Обратите внимание: getSharedPreferences () – это метод из контекста, поэтому вам нужно иметь ссылку на объект Activity или, возможно, контекст приложения в вашей AsyncTask, чтобы иметь возможность использовать его.

Кажется, что ваш код в порядке, и нет причин, по которым он не должен работать, единственной причиной может быть какой-то дефект, который, вероятно, связан с устройством. Мои мысли связаны с тем, что общие префы сохраняются в локальном хранилище. В этом процессе все может пойти не так.

Как указано в комментариях, необходимо добавить журнал типа устройства, я бы рекомендовал использовать «ACRA» – http://code.google.com/p/acra/, который может предоставить вам подробные отчеты с минимальными усилиями (Обратите внимание, что вы можете отправить отчет не обязательно только при аварии приложения).

Взгляните на эту тему, он показывает проблему, которая, возможно, вы испытываете также: SharedPreferences не будет сохранять / загружать в PreferenceActivity . Если это так, то решение будет состоять в том, чтобы вручную сохранять эти постоянные данные в локальном хранилище или использовать решение БД. Удачи 🙂

Я думаю, проблема связана с тем, что общая настройка предпочтений не записывается в вашу файловую систему, но при попытке получить к ней доступ из вашего второго действия. Вы упомянули, что вы пишете параметр из метода onPostExecute (возможно, AsyncTask ?). Когда вы запускаете AsyncTask нет никакой гарантии, что он начнется немедленно. Единственной гарантией является то, что она начнется в фоновом потоке. Платформа может и будет решать, когда фактически запускать фоновый поток, в зависимости от загрузки системы, блоков файловой системы или так далее. Вполне возможно, что ваш AsyncTask еще не запущен, когда вы переключаетесь на второе действие (и, следовательно, метод onPostExecute еще не был вызван).

Сохранение общих настроек сложно, поскольку они пишут в файловую систему. В противном случае вы можете заблокировать основной поток, если не будете осторожны. Объект SharedPreferences.Editor имеет метод apply который немедленно обновляет кеш памяти в ваших общих предпочтениях (делая изменения доступны сразу) и ударяет фоновый поток, чтобы сохранить фактическое значение в файловой системе. Поэтому мой совет будет заключаться в том, что если у вас есть такая возможность, вы должны попытаться вызвать метод apply (из основного потока) вместо метода commit из (что я предполагаю) AsyncTask . Для apply метода требуется уровень API 9 или выше.

Для справки: http://developer.android.com/reference/android/content/SharedPreferences.Editor.html

Редактировать:

Метод commit возвращает логическое значение в зависимости от результата операции записи. Вы могли бы (должны?) Проверить это возвращаемое значение, чтобы по крайней мере иметь возможность принимать правильные встречные меры при сбое (например, показать «Не удалось сохранить настройки, повторите попытку», тост или что-то еще).

Cheers, –dbm

Я могу ошибаться. Но я считаю, что мой друг имел аналогичную проблему. Я застрял в этой проблеме часами. Результаты более чем в 30% случаев не сработают. Я считаю, что onPostExecute () работает в отдельном потоке, когда экземпляр Intent создается и вызывается действие. Это связано с тем, что AsyncTask реализован в отдельном потоке. В зависимости от устройства это будет более вероятно, а затем нет. Наша таблетка редко случалась, на смартфоне это происходило бы чаще.

Вы можете проверить это, отлаживая приложение и просматривая поток AsyncThread и узнаете, когда делается вызов.

Да, лучше отправить переменную через putExtra ().

Надеюсь, это поможет вам понять, почему это произошло.

Действие commit из SharePreferences является синхронизованным, поэтому я не думаю, что тот факт, что вы начинаете новое намерение, должен его исправить, только дело в том, что действие фиксации не является безопасным, оно может выйти из строя.

http://developer.android.com/reference/android/content/SharedPreferences.Editor.html#commit ()

Возвращает true, если новые значения были успешно записаны в постоянное хранилище.

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