PreferenceFragment是否故意从兼容性软件包中排除?

我正在寻找可以应用于3.0和3.0之前的设备的首选项。 发现PreferenceActivity包含不赞成使用的方法(尽pipe这些方法在示例代码中使用),但我查看了PreferenceFragement和兼容性包来解决我的问题。

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

干杯

詹姆士

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

从Android 3.0开始,已弃用的方法已弃用。 他们在Android的所有版本上都是完美的,但方向是在Android 3.0及更高版本上使用PreferenceFragment

谁能告诉我这是故意的吗?

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

如果是这样,我可以轻松地瞄准一系列设备(即<3.0和> = 3.0),或者我将不得不跳过箍?

我认为这是“轻松”完成的。 有两个独立的PreferenceActivity实现,一个使用偏好标题和PreferenceFragments ,另一个使用原始方法。 在需要的地方select正确的(例如,当用户点击选项菜单项时)。 这是一个示范项目,展示了这一点。 或者,有一个PreferenceActivity处理这两种情况,就像这个示例项目一样 。

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

你会发现当我们其他人发现,也就是说,如果和何时发货。

还是有另一种解决方法是安全的使用?

往上看。

来自@CommonsWare的答案的微妙含义是 – 您的应用程序必须在兼容性API或内置片段API(自SDK 11左右)之间进行select。 事实上,这就是“轻松”的build议。 换句话说,如果您想使用PreferenceFragment,您的应用程序需要使用内置的片段API,并处理PreferenceActivity上的弃用方法。 相反,如果您的应用程序使用compat很重要。 API将面临根本没有PreferenceFragment类。 因此,定位设备不是问题,但是当您必须select其中一个或另一个API时发生环跳,并将您的devise提交给不可预见的解决方法。 我需要compat。 API,所以我要创build自己的PreferenceFragment类,看看它是如何工作的。 在最坏的情况下,我只是创build一个普通的(片段)布局,并将视图组件手动绑定到sharedprefs …呃。

编辑:在尝试并查看http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/preference/PreferenceFragment.java上的代码?; av = h – 创build我自己的PreferenceFragment不会发生。 似乎PreferenceManager中的自由使用package-private而不是“protected”是主要的阻止者。 这看起来确实没有任何安全性或真正的好动机,unit testing并不是很好,但是呃…less打字我猜…

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

顺便说一句 – 我说“瞄准设备不是问题”? 这完全是…如果你使用com.android.preference,你将无法在不进行重大重构的情况下使用兼容性API进行交换。 有趣的日志!

基于CommonsWare的回答以及Tenacious的观察,我想出了一个单一的后代类解决scheme,能够以最小的麻烦,无需代码或资源重复来定位所有当前的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的模拟器上testing。

见Machinarius的PreferenceFragment-Compat 。 我们很容易就放弃了,我忘了它甚至在那里。

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

重要更新: v7 support library的最新版本现在具有原生PreferenceFragmentCompat 。

2015年8月,Google发布了新的首选支持库v7 。

现在,您可以将PreferenceFragmentCompat与任何ActivityAppCompatActivity

 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以便在不影响活动的其他部分的情况下对每个首选项types使用的布局进行样式设置。

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

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

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

而且你不能通过简单地将你的实现放在android.preferences包中来解决这个问题,因为Android API中的非公共方法实际上从SDK中被忽略了。 通过一些涉及reflection和dynamic代理的创造力,你仍然可以得到它们。 如Tenacious所说,唯一的select是分叉整个android.preference包,包括至less15个类,5个布局以及类似数量的style.xml和attrs.xml元素。

所以要回答最初的问题,谷歌没有在兼容包中包含PreferenceFragment的原因是他们和Tenacious和我自己有完全一样的难度。 即使Google不能及时回到原来的平台上(尽pipe我希望他们在未来的版本中这样做)。

我的应用程序的目标是API + 14,但由于使用支持库的一些奇特的导航,我不能使用android.app.Fragment ,不得不使用android.support.v4.app.Fragment ,但我也需要有PreferenceFragment代码没有大的变化。

所以,我的简单的解决scheme有两个世界的支持库和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(); } } 

我需要在应用程序的devise中集成Preferences,并保持对2.3的支持。 所以我仍然需要PreferencesFragment。

经过一番search,我发现android-support-v4-preferencefragment lib。 这个lib节省了大量的时间来复制和重构原始的PreferencesFragment,如Tenacious所说。 工作正常,用户享受喜好。