PreferenceFragment中的RunTimeException

4

我正在跟随这个教程。在那里,使用PreferenceActivity来创建设置。然而,提到如果我愿意,可以使用Fragments,所以我前进并在普通活动中使用PreferenceFragment。但是当我运行应用程序时,它崩溃并给出以下日志 -

07-25 10:41:02.048    7515-7515/com.example.sunshine E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sunshine/com.example.sunshine.SettingsActivity}: java.lang.RuntimeException: Content has view with id attribute 'android.R.id.list' that is not a ListView class
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2063)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2088)
            at android.app.ActivityThread.access$600(ActivityThread.java:134)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4744)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.RuntimeException: Content has view with id attribute 'android.R.id.list' that is not a ListView class
            at android.preference.PreferenceFragment.ensureList(PreferenceFragment.java:350)
            at android.preference.PreferenceFragment.getListView(PreferenceFragment.java:336)
            at android.preference.PreferenceFragment.bindPreferences(PreferenceFragment.java:330)
            at android.preference.PreferenceFragment.onActivityCreated(PreferenceFragment.java:171)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:852)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1039)
            at android.app.BackStackRecord.run(BackStackRecord.java:635)
            at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1411)
            at android.app.Activity.performStart(Activity.java:5017)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2036)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2088)
            at android.app.ActivityThread.access$600(ActivityThread.java:134)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4744)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)

当我在SO上搜索时,我了解到崩溃与ListFragment有些相关。但是我确定我没有在我的应用程序中使用它。可能是PreferenceFragment调用了它。我无法确定问题所在。你能帮我解决吗?
这是我正在使用的首选项xml -
<?xml version="1.0" encoding="utf-8"?>

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <EditTextPreference
        android:title="@string/pref_location_label"
        android:key="@string/pref_location_key"
        android:defaultValue="@string/pref_location_default"
        android:inputType="text"
        android:singleLine="true"
        />
</PreferenceScreen>

以下是SettingsActivity以及相关Fragment的代码:

public class SettingsActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_settings);
        if (savedInstanceState == null) {
            getFragmentManager().beginTransaction()
                    .add(R.id.container, new SettingsFragment())
                    .commit();
        }
    }

    public static class SettingsFragment extends PreferenceFragment implements Preference.OnPreferenceChangeListener {

        public SettingsFragment() {
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // Add 'general' preferences, defined in the XML file
            addPreferencesFromResource(R.xml.pref_general);

            // For all preferences, attach an OnPreferenceChangeListener so the UI summary can be
            // updated when the preference changes.
            bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key)));
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_settings, container, false);
            return rootView;
        }

        /**
         * Attaches a listener so the summary is always updated with the preference value.
         * Also fires the listener once, to initialize the summary (so it shows up before the value
         * is changed.)
         */
        private void bindPreferenceSummaryToValue(Preference preference) {
            // Set the listener to watch for value changes.
            preference.setOnPreferenceChangeListener(this);

            // Trigger the listener immediately with the preference's
            // current value.
            onPreferenceChange(preference,
                    PreferenceManager
                            .getDefaultSharedPreferences(preference.getContext())
                            .getString(preference.getKey(), ""));
        }

        @Override
        public boolean onPreferenceChange(Preference preference, Object value) {
            String stringValue = value.toString();

            if (preference instanceof ListPreference) {
                // For list preferences, look up the correct display value in
                // the preference's 'entries' list (since they have separate labels/values).
                ListPreference listPreference = (ListPreference) preference;
                int prefIndex = listPreference.findIndexOfValue(stringValue);
                if (prefIndex >= 0) {
                    preference.setSummary(listPreference.getEntries()[prefIndex]);
                }
            } else {
                // For other preferences, set the summary to the value's simple string representation.
                preference.setSummary(stringValue);
            }
            return true;
        }
    }
}

我需要做一些什么改动才能使它适用于碎片而不是活动?


请参考 https://dev59.com/fHDYa4cB1Zd3GeqPEcwN - starbeamrainbowlabs
3个回答

4

终于找到了。我只需要在我的碎片的xml中放置一个带有android:id="@id/android:list"属性的ListView即可。虽然我不知道为什么需要这样做,但是通过试错法找到了。


3
将naveen ravindran发布的评论作为答案添加。如果有人想知道为什么添加“WORKS”,那是因为在(源代码)偏好片段-> bindpreferences()中,它实际上尝试在当前视图中查找一个listview(使用android.r.id.list),如果结果视图不是listview,则会引发上述异常。这个列表对于显示首选项是强制性的。(是的,我可以证实这也对我有效)。 - Robbie
这最终为我解决了问题。 - Ken

2

除了noob提供的解决方案之外,还有一些额外信息。 如果有人想知道为什么添加“WORKS”,那是因为在(源代码)首选项片段 --> bindpreferences()中,它实际上尝试在当前视图(使用android.r.id.list)中找到一个listview,如果结果视图不是一个listview,则会抛出上述异常。 这个列表对于显示偏好设置是必需的。


谢谢您的解释! - 0xC0DED00D

1
似乎您的问题出在您的activity_settings.xml文件中,因为它显示您(可能)创建了一个具有以下id的视图:android.R.id.list,但它不是ListView。请检查您的activity_settings.xml文件,您可能会找到问题所在,否则请发布您的XML以查看是否有问题。

谢谢!虽然我已经解决了,但你的答案接近我找到的答案。 - 0xC0DED00D

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接