Был ли PreferenceFragment намеренно исключен из пакета совместимости?

Я ищу, чтобы писать настройки, которые могут применяться как к 3.0, так и к устройствам до 3.0. Обнаружив, что PreferenceActivity содержит устаревшие методы (хотя они используются в сопроводительном примере кода), я посмотрел на PreferenceFragement и пакет совместимости для решения моих проблем.

Похоже, что PreferenceFragment не находится в пакете совместимости. Может ли кто-нибудь сказать мне, было ли это намеренно? Если да, могу ли я легко настроить диапазон устройств (т.е. <3.0 и> = 3.0), или мне придется прыгать через обручи? Если бы это не было намеренно исключено, можно ли ожидать новой версии пакета совместимости? Или есть другое решение, которое безопасно использовать?

ура

Джеймс

Обнаружение того, что PreferenceActivity содержит устаревшие методы (хотя они используются в сопроводительном примере кода)

Устаревшие методы устаревают с Android 3.0. Они отлично подходят для всех версий Android, но на самом деле нужно использовать PreferenceFragment на Android 3.0 и выше.

Может ли кто-нибудь сказать мне, было ли это намеренно?

Думаю, это вопрос инженерного времени, но это всего лишь предположение.

Если да, могу ли я легко настроить диапазон устройств (т.е. <3.0 и> = 3.0), или мне придется прыгать через обручи?

Я считаю, что это делается «легко». Имейте две отдельные реализации PreferenceActivity , используя заголовки предпочтений и PreferenceFragments , а другой – оригинальный подход. Выбирайте правильный номер в нужном вам месте (например, когда пользователь нажимает на пункт меню параметров). Вот пример проекта, демонстрирующий это. Или, у вас есть одна PreferenceActivity которая обрабатывает оба случая, как в этом примере проекта .

Если бы это не было намеренно исключено, можно ли ожидать новой версии пакета совместимости?

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

Или есть другое решение, которое безопасно использовать?

См. Выше.

Тонкое значение ответа от @CommonsWare заключается в следующем: ваше приложение должно выбирать между API совместимости или встроенным API-интерфейсом фрагмента (с SDK 11 или около того). На самом деле это то, что сделала «легко» рекомендация. Другими словами, если вы хотите использовать PreferenceFragment, ваше приложение должно использовать встроенный API-интерфейс фрагмента и работать с устаревшими методами в PreferenceActivity. И наоборот, если важно, чтобы ваше приложение использовало совместимость. API вы столкнетесь с отсутствием класса PreferenceFragment. Таким образом, устройства с таргетингом не являются проблемой, но обруч происходит, когда вам нужно выбрать один или другой API и, таким образом, представить свой проект в непредвиденные способы обхода. Мне нужна компаньона. API, поэтому я собираюсь создать свой собственный класс PreferenceFragment и посмотреть, как это работает. В худшем случае я просто создаю обычный (фрагмент) макет и привяжу компоненты представления к sharedprefs вручную … тьфу.

РЕДАКТИРОВАТЬ: После попытки просмотра кода на странице http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/preference/PreferenceFragment.java? Av = h – создание собственного PreferenceFragment не произойдет. Похоже, что либеральное использование пакета-частного в PreferenceManager вместо «защищенного» является основным блокиратором. На самом деле не похоже, что есть какая-либо безопасность или действительно хорошая мотивация, чтобы сделать это, и это не очень удобно для модульного тестирования, но, о, хорошо … меньше набрав, я думаю …

EDIT v2: На самом деле это произошло, и это сработало. Это была определенная головная боль, чтобы заставить код работать с JAR совместимости API. Мне пришлось скопировать около 70% пакета com.android.preference из SDK в мое приложение, а затем бороться с типично средним качеством Java-кода на Android. Я использовал v14 SDK. Инженеру Goog было бы намного легче делать то, что я делал, вопреки тому, что я слышал, некоторые инженеры из Android говорят об этой теме.

BTW – я сказал, что «устройства таргетинга не являются проблемой»? Это полностью … если вы используете com.android.preference, вы не сможете поменять его на API совместимости без большого рефакторинга. Веселый журнал!

Основываясь на ответе CommonsWare, а также на наблюдениях Tenacious, я придумал одно решение класса потомков, которое может ориентироваться на все текущие версии Android API с минимальным шумом и отсутствием дублирования кода или ресурсов. См. Мой ответ на соответствующий вопрос: PreferenceActivity Android 4.0 и более ранние версии

Или в моем блоге: http://www.blackmoonit.com/2012/07/all_api_prefsactivity/

Протестировано на двух планшетах с версиями 4.0.3 и 4.0.4, а также на телефоне с 4.0.4 и 2.3.3, а также на эмуляторе под управлением 1.6.

См. PreferenceFragment-Compat от Machinarius. Легко заглянуть в град, и я забыл, что он даже там.

compile 'com.github.machinarius:preferencefragment:0.1.1'

Важное обновление: последняя версия v7 support library теперь имеет собственный PreferenceFragmentCompat .

В августе 2015 года Google выпустила новую библиотеку поддержки предпочтений v7 .

Теперь вы можете использовать PreferenceFragmentCompat с любой Activity или AppCompatActivity

 public static class PrefsFragment extends PreferenceFragmentCompat { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Load the preferences from an XML resource addPreferencesFromResource(R.xml.preferences); } } 

Вы должны установить preferenceTheme в своей теме:

 <style name="AppTheme" parent="@style/Theme.AppCompat.Light"> ... <item name="preferenceTheme">@style/PreferenceThemeOverlay</item> </style> 

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

Ответ Tenacious верен, но вот некоторые подробности.

Причина, по которой вы не можете «создать нормальный макет и привязать компоненты представления к sharedprefs вручную», заключается в том, что в API android.preferences есть некоторые неожиданные упущения. PreferenceActivity и PreferenceFragment имеют доступ к критическим непубличным методам PreferenceManager, без которых вы не можете реализовать собственный пользовательский интерфейс предпочтений.

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

И вы не можете обойти это, скрывая вашу реализацию в пакете android.preferences, потому что непубличные методы в API Android фактически исключены из SDK. С небольшим количеством творчества, включающим отражение и динамические прокси-серверы, вы все равно можете добраться до них. Единственная альтернатива, как говорит Tenacious, заключается в том, чтобы развернуть весь пакет android.preference, включая как минимум 15 классов, 5 макетов и аналогичное количество элементов style.xml и attrs.xml.

Поэтому, чтобы ответить на исходный вопрос, причина, по которой Google не включила PreferenceFragment в пакет совместимости, заключается в том, что у них была бы такая же сложность, как и Tenacious и я. Даже Google не может вернуться во времени и сделать эти методы общедоступными на старых платформах (хотя я надеюсь, что они это сделают в будущих выпусках).

Цель моего приложения – API +14, но из-за использования библиотеки поддержки для какой-то причудливой навигации я не мог использовать android.app.Fragment и должен был использовать android.support.v4.app.Fragment , но мне также нужно было иметь PreferenceFragment На месте без больших изменений кода.

Таким образом, мое легкое решение о наличии как миров поддержки библиотеки, так и PreferenceFragment :

 private android.support.v4.app.Fragment fragment; private android.app.Fragment nativeFragment = null; private void selectItem(int position) { fragment = null; boolean useNativeFragment = false; switch (position) { case 0: fragment = new SampleSupprtFragment1(); break; case 1: fragment = new SampleSupprtFragment2(); break; case 2: nativeFragment = new SettingsFragment(); useNativeFragment = true; break; } if (useNativeFragment) { android.app.FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.content_frame, nativeFragment).commit(); } else { if (nativeFragment != null) { getFragmentManager().beginTransaction().remove(nativeFragment) .commit(); nativeFragment = null; } FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.content_frame, fragment).commit(); } } 

Мне нужно было интегрировать Preferences в дизайн приложения и поддерживать поддержку 2.3 android. Поэтому мне все еще нужны PreferencesFragment.

После некоторого поиска я нашел android-support-v4-preferencefragment lib. Этот lib сэкономит много времени на копирование и рефакторинг оригинальных PreferencesFragment как Tenacious. Прекрасно работает, и пользователи пользуются преференциями.