【问题标题】:What to use instead of "addPreferencesFromResource" in a PreferenceActivity?在 PreferenceActivity 中使用什么来代替“addPreferencesFromResource”?
【发布时间】:2011-10-12 22:23:55
【问题描述】:

我刚刚注意到 addPreferencesFromResource(int preferencesResId) 方法在 Android 的文档 (Reference Entry) 中被标记为已弃用

很遗憾,该方法的描述中没有提供替代方法。

应该使用哪种方法来将preferenceScreen.xml 连接到匹配的PreferenceActivity?

【问题讨论】:

  • WannaGetHigh 在stackoverflow.com/questions/23523806/…提供了一个非常简单的方法
  • 那里的解决方案仍然使用addPreferencesFromResource(int preferencesResId)。我错过了什么吗?
  • @Jammo 是的,但它已从 Activity 移至 Fragment 以反映新的操作方式 -> 片段。

标签: android xml


【解决方案1】:

该方法的描述中没有提供替代方法,因为首选方法(从 API 级别 11 开始)是实例化 PreferenceFragment 对象以从资源文件加载您的首选项。在此处查看示例代码:PreferenceActivity

【讨论】:

  • 非常感谢您的回答。我只是按照“Video2Brain-Android Development”中已弃用的说明进行操作,这导致我使用了 PreferenceActivity 的方法版本。顺便说一句:如果可以的话,我很乐意将您的回答评为有用。
  • 现在只有当 PreferenceFragment 包含在兼容性包中时才有意义使用它stackoverflow.com/questions/5501431/…
  • 由于我用的是Action Bar Sherlock,所以就跟着下面的博客解决了这个问题,见...commonsware.com/blog/2012/10/16/…
  • 如果您希望应用程序向后兼容 11 (Android 3.0) 之前的 api 级别,您仍然需要调用 addPreferencesFromResource(int PreferencesID)。但我想你也可以考虑弃用那些旧设备。
  • @EinarSundgren 我是 Nexus One 的拥有者,我的最高可用版本是 2.2:你不会阻止我的!我永远不会被弃用!靠灰骷髅的力量……我有力量!
【解决方案2】:

要为上面的正确答案添加更多信息,在阅读example from 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);
        }
    }
}

从片段中做出更复杂的偏好可能还有其他微妙之处;如果是这样,我希望有人在这里注意到它们。

【讨论】:

  • 很好,谢谢。 Java 和这种类型的思维与我美好的 .net 世界相去甚远 :)
  • 他们为什么要在 PreferenceFragment 的交易中贬值 addPreferencesFromResources()?从初学者的角度来看,它看起来没有必要。
  • 调用需要 API 级别 11
  • 那么如果 API 处于第 9 级呢? @mehmet
  • 很棒的答案!有没有办法在不改变 android.R.id.content 的情况下实现这一点?由于某种原因对我来说似乎不优雅......(如果我错了,请纠正我)
【解决方案3】:

@Garret Wilson 非常感谢!作为一个 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)中测试成功。

为什么我的代码看起来如此糟糕:

我是一个 android 编码的菜鸟,我不是最棒的 java 粉丝。

为了避免弃用警告并强制 Eclipse 允许我进行编译,我不得不求助于注释,但这些似乎只影响类或方法,所以我不得不将代码移动到两个新方法上以利用这个。

我不希望每次复制和粘贴新 PreferenceActivity 的类时都必须写两次我的 xml 资源 ID,因此我创建了一个新变量来存储该值。

我希望这对其他人有用。

P.S.:对不起我的固执己见,但是当你新来的时候发现这样的障碍,你会忍不住沮丧!

【讨论】:

  • 哦,好吧...我刚刚注意到,每当我复制和粘贴它时,我都必须更改外部类名两次。实际上有一种方法可以避免这种情况,通过将首选项传递给内部类。您不能创建一个接受首选项作为参数的内部类构造函数,因为显然不建议将它用于 PreferenceFragment 派生类。此外,您可能不会在内部类中创建一个方法来获取首选项并立即调用 addPreferencesFromResource,因为 addPreferencesFromResource 需要在调用 super.onCreate 之后调用,而 onCreate 不会在 PreferenceFragment 派生类之后立即调用...
  • ...已实例化。所以你需要在内部类中创建一个新变量,在内部类中为它创建一个公共的set方法,在调用super.onCreate之后将addPreferencesFromResource留在它所在的位置,在onCreate内部,实例化内部类,设置prefs , 并像以前一样在调用 getFragmentManager()... 时使用它。
  • 您的代码是救命稻草!!我试图同时针对旧手机和新手机,浪费了 3 天。答案很简单。谢谢
【解决方案4】:

不用例外,只需使用:

if (Build.VERSION.SDK_INT >= 11)

并使用

@SuppressLint("NewApi")

抑制警告。

【讨论】:

  • 因为它只会崩溃:D
  • 如果它崩溃了......然后尝试抓住它:D
【解决方案5】:

我的方法非常接近Garret Wilson's(谢谢,我投票支持你;)

此外,它还提供与 Android

我刚刚意识到我的解决方案更接近Kevin Remo 的解决方案。它只是更干净一点(因为它不依赖于"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();
    }
}

有关“真实”(但更复杂)的示例,请参阅 NusicPreferencesActivityNusicPreferencesFragment

【讨论】:

  • @SuppressLint("NewApi") - 避免 - 更准确。您是否为低 api 运行过它?它会抛出VerifyError
  • 我在运行 API 级别 10 的模拟器上测试了上述内容,APK 是使用 SDK 版本 19 构建的。您构建时使用的 SDK 版本是什么?您在什么设备 API 级别上运行它?你是在模拟器上运行的还是在物理设备上运行的?错误究竟是什么时候发生的?如果 Ur 使用 SDK this response。
  • 您错过了重点 - 如果您希望我收到通知,请添加 @Mr_and_Mrs_D。对于 VE,请在此处阅读:stackoverflow.com/questions/20271593/…@SuppressLint("NewApi") 风格不好
  • @M 那么,关于如何在这种特殊情况下避免@SuppressLint("NewApi") 的建议如何?
  • @TargetApi(Build.VERSION_CODES.HONEYCOMB) - 并非针对任何 api 的所有警告 :)
【解决方案6】:

不要使用PreferenceActivity 直接加载首选项,而是使用AppCompatActivity 或等效的加载PreferenceFragmentCompat 来加载您的首选项。它是支持库(现为 Android Jetpack)的一部分,并提供与 API 14 的兼容性。

在您的build.gradle 中,添加首选项支持库的依赖项:

dependencies {
    // ...
    implementation "androidx.preference:preference:1.0.0-alpha1"
}

注意:我们假设您已经创建了偏好 XML。

为您的活动创建一个新的活动类。如果您使用的是材料主题,您应该扩展一个 AppCompatActivity,但您可以灵活使用:

public class MyPreferencesActivity extends AppCompatActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_preferences_activity)
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, MyPreferencesFragment())
                    .commitNow()
        }
    }
}

现在是重要的部分:创建一个从 XML 加载您的首选项的片段:

public class MyPreferencesFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.my_preferences_fragment); // Your preferences fragment
    }
}

如需了解更多信息,请阅读 Android 开发者docs for PreferenceFragmentCompat

【讨论】:

    猜你喜欢
    • 2013-04-28
    • 1970-01-01
    • 2020-05-15
    • 2011-10-02
    • 1970-01-01
    • 2018-11-24
    • 2023-03-30
    • 2011-09-23
    • 1970-01-01
    相关资源
    最近更新 更多