当前位置: 首页 > 知识库问答 >
问题:

在android中旋转设备后出现异常,因为片段类中缺少公共construcotr方法

拓拔阎宝
2023-03-14

我写了一个非常简单的程序,其中有一个包含片段的活动。我将片段构造函数设为私有,并且我使用静态newInstance()方法返回片段。当我旋转手机时,问题就开始了。我得到一个异常,它说:

无法启动活动ComponentInfo{com.example.todeleteimmediatley/com.example.MainActivity}:androidx.fragment.app.片段$InstantiationException:无法实例化片段com.example.日期片段:找不到片段构造函数

我调试了程序,发现异常在onCreate方法的第一行(调用super.onCreate()时)。有人可以解释为什么片段必须有一个构造函数,以及为什么在super中发生异常。onCreate()阶段?

共有2个答案

隆康平
2023-03-14

在Java

>

如果类定义了任何具有参数的构造函数,那么在编译时,编译器将不会生成默认构造函数。

有人可以解释为什么片段必须有构造函数?

如果片段没有收到任何参数,则不需要定义构造函数。

为什么在super中发生异常。onCreate()阶段?

在Android中,系统需要重新创建活动时有几种场景,例如。

>

系统内存不足时

重新创建活动时,系统将创建该活动的新实例,然后调用活动生命周期,第一个实例将是回调。在活动(例如MainActivity)中,需要调用super。其父对象的onCreate()。此语句将还原由活动管理的所有片段(例如,在您的示例中为DatesFragment)。

因为这是Mainactive的一个新实例,所以它还需要创建所有托管片段(包括Dates片段)的新实例。为此,他们将调用默认参数构造函数。

但是在DatesFragment中,您使默认构造函数是私有的,这意味着它只能在该类内访问,系统无法调用DatesFragment类的构造函数,因此它们抛出实例化异常。

解决方案:

>

如果需要将参数传递给片段,则使用默认构造函数和setArguments(Bundle)

姚信鸥
2023-03-14

当您旋转设备时,您的活动将被破坏并重新创建。其中一部分是销毁和重新创建活动托管的任何片段。

在重新创建步骤中,Android框架需要实例化片段的新实例。默认情况下,它通过调用片段的无参数构造函数来实现。这意味着该构造函数必须(a)存在并且(b)是公共的。

碎片的这种再创作是由活动的super.onCreate()触发的。

一般建议创建一个工厂方法(正如您所做的那样),但不要使用默认构造函数(即不要使其私有)。是的,这意味着有人仍然可以直接调用构造函数,这是您不想要的,但如果您不想参与碎片工厂(FragmentFactory)。

这是否意味着在onCreate中,我应该在添加和提交之前检查容器是否已经包含片段?因为正如我从您那里了解到的,onCreate()。super将恢复旧碎片。

我在这里的建议是只在活动第一次启动时提交片段事务一次。通常,这是通过在提交事务之前检查savedInstanceState包是否为空来实现的:

if (savedInstanceState == null) {
    getSupportFragmentManager().beginTransaction()
            .replace(R.id.foo, FooFragment.newInstance(...))
            .commit();
}

因为您的片段是活动实例状态的一部分,所以任何娱乐(任何时候savedInstanceState不是null)都将自动为您处理。

为什么在newInstance方法中更好地将片段所需的信息添加到Bundle中,而不是将它们存储为片段的成员(属性)?

一切都回到了Android框架需要创建片段的新实例这一事实上。如果你只是在你设置的片段上有成员字段,Android框架将不会意识到这些,也无法保存或恢复它们。

然而,Android确实知道参数包。参数被视为片段实例状态的一部分(因此也是包含活动的实例状态的一部分),并将自动保存和恢复。这就是为什么您只能将某些类型的数据放入参数包;Android只知道在这个重新创建过程中如何“写”和“读”某些类型的数据。

 类似资料:
  • 我试图展示一个祝酒词,当我的API请求不工作,由于没有互联网连接。首先,我尝试在try块失败时显示一个Toast,然后在catch块中显示这个Toast。我尝试了developer.android.com的方法,但我甚至无法启动应用程序。 我在catch-block中的代码是这样的: 我似乎对方法有问题,因为它突出显示为红色。这似乎是一个问题,因为我在一个片段内部使用这个。我在使用时读到了一些内容

  • 我对片段有问题,或者更确切地说是我希望它们工作的方式有问题。 在我的活动中,我有一个布局容器(R.id.container1),我在启动时以编程方式向其中添加一个片段(FragMain)。在片段中,我有2个片段(Frag1、Frag2)和一个ViewPager,它通过FragmentPagerAdapter加载其他几个片段(FragA、FragB、FragC、FragD、FragE)。 按下一个按

  • 我有一个片段,在这里我调用自定义视图类(Dragger) 并且我有另一个片段与和适配器,在其中我调用方法通过主机的活动的。 我发现在中旋转后会获得新的引用,但当我从适配器调用时-为空。 我真的不明白为什么字段得到引用,然后又丢失了它) 有人知道这有什么不对吗? 提前谢谢! P. S.:主机活动

  • 公共视图onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){View v=inflater.inflate(r.layout.fragment_main,container,false); fragment.xml null

  • 问题内容: 我有一个齿轮图像,我想绕固定点连续旋转。 之前,我是通过将图像作为ImageView包含在我的Android类中并对其应用RotateAnimation来实现的。 RotateAnimation ra07 = new RotateAnimation(0, 359, 129, 186); ra07.setDuration(10000); ra07.setRepeatCount(Rotat

  • 我有一个字符串包含这个。注意,JSON中没有“name”字段。如果我做了这样的事情: 然后我实际上会返回一个名称设置为null的Person对象。是否有一种方法可以将映射器配置为抛出异常,或者返回空引用而不是Person?我希望Jackson认为缺少字段是一种失败,而不希望对结果对象的字段进行显式的空检查。