Что использовать вместо "addPreferencesFromResource" в PreferenceActivity?
Я только заметил, что метод addPreferencesFromResource(int preferencesResId)
отмечен устаревшим в документации по Android (Reference Entry).
К сожалению, альтернативный метод не указан в описании метода.
Какой метод следует использовать вместо этого, чтобы связать preferenceScreen.xml с подходящей PreferenceActivity?
Ответы
Ответ 1
В описании метода нет альтернативного метода, потому что предпочтительный подход (с уровня API уровня 11) заключается в создании экземпляров PreferenceFragment объектов загрузите свои настройки из файла ресурсов. См. Пример кода здесь: PreferenceActivity
Ответ 2
Чтобы добавить дополнительную информацию к правильному ответу выше, после чтения примера из Android-er, я обнаружил, что вы можете легко преобразовать свою активность предпочтений в фрагмент предпочтения. Если у вас есть следующее действие:
public class MyPreferenceActivity extends PreferenceActivity
{
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.my_preference_screen);
}
}
Единственные изменения, которые вы должны сделать, это создать внутренний класс фрагмента, переместить addPreferencesFromResources()
в фрагмент и вызвать фрагмент из действия, например:
public class MyPreferenceActivity extends PreferenceActivity
{
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
}
public static class MyPreferenceFragment extends PreferenceFragment
{
@Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.my_preference_screen);
}
}
}
Могут быть другие тонкости для создания более сложных предпочтений из фрагментов; если так, надеюсь, кто-то заметит их здесь.
Ответ 3
@Garret Wilson Большое вам спасибо! Как noob для кодирования Android, я застрял с проблемой несовместимости предпочтений в течение стольких часов, и я нахожу это настолько разочаровывающим, что они не рекомендуют использовать некоторые методы/подходы для новых, которые не поддерживаются более старыми API, таким образом прибегая к разным обходным решениям, чтобы ваше приложение работало на широком спектре устройств. Это действительно расстраивает!
Ваш класс замечательный, поскольку он позволяет вам работать в новых API с предпочтениями так, как раньше, но не поддерживает обратную совместимость. Поскольку я пытаюсь охватить широкий спектр устройств, я немного потрудился, чтобы он работал в устройствах с поддержкой API 11, а также в новых API:
import android.annotation.TargetApi;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
public class MyPrefsActivity extends PreferenceActivity
{
private static int prefs=R.xml.myprefs;
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
try {
getClass().getMethod("getFragmentManager");
AddResourceApi11AndGreater();
} catch (NoSuchMethodException e) { //Api < 11
AddResourceApiLessThan11();
}
}
@SuppressWarnings("deprecation")
protected void AddResourceApiLessThan11()
{
addPreferencesFromResource(prefs);
}
@TargetApi(11)
protected void AddResourceApi11AndGreater()
{
getFragmentManager().beginTransaction().replace(android.R.id.content,
new PF()).commit();
}
@TargetApi(11)
public static class PF extends PreferenceFragment
{
@Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(MyPrefsActivity.prefs); //outer class
// private members seem to be visible for inner class, and
// making it static made things so much easier
}
}
}
Успешно протестировано в двух эмуляторах (2.2 и 4.2).
Почему мой код выглядит так дерьмово:
Я noob для кодирования Android, и я не самый большой поклонник java.
Чтобы избежать устаревшего предупреждения и заставить Eclipse разрешить мне скомпилировать, мне приходилось прибегать к аннотациям, но они, похоже, влияют только на классы или методы, поэтому мне пришлось переместить код на два новых метода, чтобы воспользоваться преимуществами из этого.
Мне не хотелось бы писать свой идентификатор ресурса xml дважды в любое время, когда я копирую и вставляю класс для новой PreferenceActivity, поэтому я создал новую переменную, чтобы сохранить это значение.
Я надеюсь, что это будет полезно кому-то другому.
P.S.: Извините за мои упрямые взгляды, но когда вы приходите новыми и находите такие недостатки, вы не можете помочь, но расстраиваться!
Ответ 4
Мой подход очень близок к Гаррету Уилсону (спасибо, я проголосовал за вас;)
Кроме того, он обеспечивает понижающую совместимость с Android < 3.
Я только узнал, что мое решение еще ближе к тому, что было сделано Кевином Ремо. Это просто немного чище (поскольку он не полагается на "expection" antipattern).
public class MyPreferenceActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
onCreatePreferenceActivity();
} else {
onCreatePreferenceFragment();
}
}
/**
* Wraps legacy {@link #onCreate(Bundle)} code for Android < 3 (i.e. API lvl
* < 11).
*/
@SuppressWarnings("deprecation")
private void onCreatePreferenceActivity() {
addPreferencesFromResource(R.xml.preferences);
}
/**
* Wraps {@link #onCreate(Bundle)} code for Android >= 3 (i.e. API lvl >=
* 11).
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void onCreatePreferenceFragment() {
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new MyPreferenceFragment ())
.commit();
}
}
Для "реального" (но более сложного) примера см. NusicPreferencesActivity и NusicPreferencesFragment.
Ответ 5
Вместо исключений просто используйте:
if (Build.VERSION.SDK_INT >= 11)
и используйте
@SuppressLint("NewApi")
для подавления предупреждений.