InstantiationException:无法实例化片段确保 class 名称存在,是 public,并且有一个空的构造函数是 public

InstantiationException: Unable to instantiate fragment make sure class name exists, is public, and has an empty constructor that is public

我有一个最初使用 Android Studio 开发的项目。我决定将其转换为 Xamarin (Visual Studio 2015)。

经过数小时的移植所有代码后,除了我的设置 activity (PreferenceActivity) 之外,一切正常。我有一些构成设置的 PreferenceFragments,但它们都给我 "Unable to instantiate fragment"。这是我得到的异常:

Java.Lang.RuntimeException: Unable to start activity ComponentInfo{test.mypackagename/md50d00e677e41fc49f8b3c16e79df2b77f.SettingsActivity}: android.app.Fragment$InstantiationException: Unable to instantiate fragment test.mypackagename.GeneralPreferenceFragment: make sure class name exists, is public, and has an empty constructor that is public

我一直在网上寻找解决方案,但似乎找不到。我到处看他们都说确保有一个空的 public 构造函数,如果它是一个内部 class 它必须是静态的。但是我有一个空的构造函数,它不是一个内部 class,它在它自己的文件中。

这是我的 SettingsActivity.cs:

namespace test.mypackagename
{
    public class SettingsActivity : PreferenceActivity
    {
        protected override void OnPostCreate(Bundle savedInstanceState)
        {
            base.OnPostCreate(savedInstanceState);
        }

        public override void OnBuildHeaders(IList<Header> target)
        {
            LoadHeadersFromResource(Resource.Xml.pref_headers, target);
        }
    }
}

这是我的 GeneralPreferenceFragment.cs:

namespace test.mypackagename
{
    public class GeneralPreferenceFragment : PreferenceFragment
    {
        public GeneralPreferenceFragment() { }

        public override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            AddPreferencesFromResource(Resource.Xml.pref_general);
        }
    }
}

这是我的 pref_headers.xml:

<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">

    <header android:fragment="test.mypackagename.GeneralPreferenceFragment"
        android:title="@string/pref_header_general" />

    <header android:fragment="test.mypackagename.OtherPreferenceFragment1"
        android:title="@string/pref_header_other1" />

    <header android:fragment="test.mypackagename.OtherPreferenceFragment2"
        android:title="@string/pref_header_other2" />

    <header android:fragment="test.mypackagename.OtherPreferenceFragment3"
        android:title="@string/pref_header_other3" />

    <header android:fragment="test.mypackagename.OtherPreferenceFragment4"
        android:title="@string/pref_header_other4" />

</preference-headers>

这之前工作正常,所以我不确定问题出在哪里。任何帮助将不胜感激。

我认为你 运行 遇到了这个问题,因为当你的 PreferenceFragment 上没有使用 [Register] 属性时,它的名称会附加 Xamarin 的 MD5 和。

因此,为了在 pref_headers.xml 中实际拥有您期望的名称空间,您需要将 class:

归因于
[Register("test.mypackagename.GeneralPreferenceFragment")]
public class GeneralPreferenceFragment: PreferenceFragment
{
    // code here
}

编辑:

我刚刚测试了代码,它在我的机器上运行良好。我没有使用任何支持包或任何东西。

pref_general.xml

<?xml version="1.0" encoding="utf-8" ?> 
<PreferenceScreen
        xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
            android:title="durr">
        <CheckBoxPreference
                android:key="checkbox_preference"
                android:title="herp"
                android:summary="derp" />
    </PreferenceCategory>
</PreferenceScreen>

pref_headers.xml

<?xml version="1.0" encoding="utf-8" ?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
  <header android:fragment="test.mypackagename.GeneralPreferenceFragment"
      android:title="general" />
</preference-headers>

SettingsActivity.cs

[Activity(Label = "SettingsActivity")]
public class SettingsActivity : PreferenceActivity
{
    public override void OnBuildHeaders(IList<Header> target)
    {
        LoadHeadersFromResource(Resource.Xml.pref_headers, target);
    }
}

GeneralPreferenceFragment.cs

[Register("test.mypackagename.GeneralPreferenceFragment")]
public class GeneralPreferenceFragment : PreferenceFragment
{
    public override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        AddPreferencesFromResource(Resource.Xml.pref_general);
    }
}

这很好用,应用程序首先显示 SettingsActivity 常规选项,点击后显示标题和 CheckBox

即使没有向 GeneralPreferenceFragment 提供任何构造函数,这也能奏效。但是,您可以尝试添加这些:

public GeneralPreferenceFragment()
{
}

public GeneralPreferenceFragment(IntPtr javaRef, JniHandleOwnership transfer)
    : base(javaRef, transfer)
{
}

当应用程序从后台返回或当 Java 世界以某种方式调用 class 时,通常需要后一个 ctor。