是否故意将PreferenceFragment排除在兼容性包之外?

时间:2011-03-31 14:27:08

标签: android compatibility android-3.0-honeycomb

我正在寻找可以应用于3.0和3.0之前的设备的首选项。发现PreferenceActivity包含已弃用的方法(虽然这些方法在随附的示例代码中使用),但我查看了PreferenceFragement和兼容包来解决我的困境。

但似乎PreferenceFragment不在兼容包中。谁能告诉我这是否是故意的?如果是这样,我可以轻松地定位一系列设备(即< 3.0和> = 3.0),还是我必须跳过篮球?如果没有故意排除,我们是否可以期待兼容包的新版本?或者是否有另一种可以安全使用的解决方法?

干杯

詹姆斯

8 个答案:

答案 0 :(得分:90)

  

发现PreferenceActivity包含已弃用的方法(尽管这些方法在随附的示例代码中使用)

自Android 3.0起,不推荐使用已弃用的方法。它们适用于所有Android版本,但方向是在Android 3.0及更高版本上使用PreferenceFragment

  

有谁能告诉我这是否是故意的?

我的猜测是工程时间问题,但这只是猜测。

  

如果是这样,我可以轻松定位一系列设备(即< 3.0和> = 3.0),还是必须跳过篮球?

我认为这很容易“完成”。有两个单独的PreferenceActivity实现,一个使用首选项标头和PreferenceFragments,另一个使用原始方法。在您需要的位置选择正确的位置(例如,当用户点击选项菜单项时)。 Here is a sample project证明了这一点。或者,只有一个PreferenceActivity来处理这两种情况,例如this sample project

  

如果没有故意排除,我们是否可以期待兼容包的新版本?

你会发现我们其他人何时发现,也就是说,它是否以及何时发货。

  

或者是否有另一种可以安全使用的解决方法?

见上文。

答案 1 :(得分:21)

来自@CommonsWare的答案的微妙含义是 - 您的应用必须在兼容性API或内置片段API之间进行选择(自SDK 11以来)。事实上,这就是“轻松”推荐所做的事情。换句话说,如果您想使用PreferenceFragment,您的应用需要使用内置片段API并处理PreferenceActivity上不推荐使用的方法。相反,如果您的应用程序使用compat很重要。您将面临的API根本没有PreferenceFragment类。因此,定位设备不是问题,但是当您必须选择一个或另一个API并因此将您的设计提交给无法预见的变通方法时,就会发生跳跃。我需要compat。 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中自由使用package-private而不是'protected'是主要阻止程序。它真的看起来没有任何安全性或真正好的动力来完成它并且它对于单元测试来说并不是很好但是哦......很少打字我猜...

编辑v2: 实际上它确实发生了并且有效。使代码与兼容性API JAR一起工作绝对令人头疼。我不得不将大约70%的com.android.preference软件包从SDK复制到我的应用程序,然后在Android中与典型的中等质量Java代码搏斗。我使用了v14的SDK。对于一个Goog工程师来说,做我做的事情要容易得多,这与我听到一些Android工程师对这个话题所说的相反。

BTW - 我说“定位设备不是问题”吗?它完全是......如果你使用com.android.preference,你将无法在没有重大重构的情况下更换兼容性API。有趣的日志!

答案 2 :(得分:16)

建立在CommonsWare的答案以及顽强的'观察,我已经提出了一个单一的后代类解决方案,能够针对所有当前的Android API版本进行最小的麻烦,没有代码或资源重复。请在此处查看我对相关问题的回答: PreferenceActivity Android 4.0 and earlier

或在我的博客上: http://www.blackmoonit.com/2012/07/all_api_prefsactivity/

在运行4.0.3和4.0.4的两款平板电脑以及运行4.0.4和2.3.3的手机以及运行1.6的模拟器上进行了测试。

答案 3 :(得分:10)

见Machinarius的PreferenceFragment-Compat。很容易陷入困境,我忘了它甚至在那里。

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

重要更新: v7 support library的{​​{3}}现在有一个原生latest revision

答案 4 :(得分:10)

2015年8月,Google发布了新的Preference Support Library v7

现在,您可以将PreferenceFragmentCompatActivityAppCompatActivity

一起使用
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以设置用于每种首选项类型的布局样式,而不会影响活动的其他部分。

答案 5 :(得分:7)

顽强的回答是正确的,但这里有更多细节。

你不能“创建一个正常的布局并手动将视图组件绑定到sharedprefs”的原因是android.preferences API中有一些令人惊讶的遗漏。 PreferenceActivity和PreferenceFragment都可以访问关键的非公共PreferenceManager方法,否则您无法实现自己的首选项UI。

特别是,要从XML文件构造Preference层次结构,您需要使用PreferenceManager,但所有PreferenceManager的构造函数都是包私有或隐藏的。将Preference onClick侦听器附加到您的活动的方法也是package-private。

你不能通过偷偷把你的实现放在android.preferences包中来解决这个问题,因为Android API中的非公共方法实际上是从SDK中省略的。通过一些涉及反射和动态代理的创造力,您仍然可以获得它们。正如Tenacious所说,唯一的选择是分叉整个android.preference包,包括至少15个类,5个布局,以及类似数量的style.xml和attrs.xml元素。

所以为了回答最初的问题,谷歌在兼容性软件包中没有包含PreferenceFragment的原因是他们会遇到与Tenacious和我一样的难度。即便谷歌也无法及时回归并在旧平台上公开这些方法(尽管我希望他们在未来的版本中这样做)。

答案 6 :(得分:2)

我的应用目标是API + 14,但是由于使用支持库进行了一些奇特的导航,我无法使用android.app.Fragment并且必须使用android.support.v4.app.Fragment,但我还需要PreferenceFragment 1}}到位后没有对代码进行大的更改。

所以我很容易找到支持库和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();
    }
}

答案 7 :(得分:2)

我需要将Preferences集成到应用程序的设计中并继续支持2.3 android。所以我仍然需要PreferencesFragment。

经过一番搜索,我找到了android-support-v4-preferencefragment lib。正如Tenacious所说,这个lib节省了大量复制和重构原始PreferencesFragment的时间。工作正常,用户喜欢偏好。