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


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

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

Ура

Джеймс

8 153

8 ответов:

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

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

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

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

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

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

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

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

или есть другой обходной путь, который является безопасным для использования?

см. выше.

тонкий смысл ответа от @CommonsWare заключается в том, что ваше приложение должно выбирать между API совместимости или встроенным API фрагментов (начиная с SDK 11 или около того). На самом деле это то, что сделала рекомендация" легко". Другими словами, если вы хотите использовать PreferenceFragment ваше приложение должно использовать встроенный фрагмент API и иметь дело с устаревшими методами на PreferenceActivity. И наоборот, если важно, чтобы ваше приложение использовало compat. 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 не произойдет. Похоже, что либеральное использование package-private в PreferenceManager вместо "protected" является основным блокировщиком. Это действительно не похоже на то, что есть какая-то безопасность или действительно хорошая мотивация, чтобы сделать это, и это не очень хорошо для модульного тестирования, но хорошо...меньше печатать Я думаю...

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

кстати - я сказал "таргетинг устройства не проблема"? Это точно так...если вы используете com.андроид.предпочтение вы не сможете поменять местами с API совместимости без серьезного рефакторинга. Веселый журнал!

основываясь на ответе CommonsWare, а также на наблюдениях Tenacious, я придумал одно решение класса потомков, способное ориентироваться на все текущие версии API Android с минимальной суетой и без дублирования кода или ресурсов. Пожалуйста, смотрите мой ответ на соответствующий вопрос здесь: 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. Было легко зайти с gradle, и я забыл, что он даже там.

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

Важное Замечание: The последние изменения на 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 вручную", заключается в том, что в android есть некоторые удивительные упущения.настройки API. PreferenceActivity и PreferenceFragment оба имеют доступ к критическим непубличным методам PreferenceManager, без которых вы не можете реализовать собственный пользовательский интерфейс предпочтений.

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

и вы не можете обойти это, тайком поставив свою реализацию в android.пакет предпочтений, поскольку непубличные методы в API-интерфейсах Android фактически опущены из SDK. С немного творчества с участием рефлексии и динамические прокси, вы все еще можете получить на них. Единственная альтернатива, как говорит цепкий, - это раскошелиться на весь android.пакет предпочтений, включающий не менее 15 классов, 5 макетов и аналогичное количество стилей.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();
    }
}

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

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