【问题标题】:java.lang.NoSuchMethodException for onCreateonCreate 的 java.lang.NoSuchMethodException
【发布时间】:2019-06-19 13:32:59
【问题描述】:

我在 Google Play 崩溃日志中看到了崩溃,这让我很困惑。

java.lang.RuntimeException: 
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3086)
  at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3229)
  at android.app.servertransaction.LaunchActivityItem.execute (LaunchActivityItem.java:78)
  at android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:108)
  at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:68)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1926)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loop (Looper.java:214)
  at android.app.ActivityThread.main (ActivityThread.java:6981)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1445)
Caused by: androidx.fragment.app.Fragment$InstantiationException: 
  at androidx.fragment.app.Fragment.instantiate (Fragment.java:462)
  at androidx.fragment.app.FragmentContainer.instantiate (FragmentContainer.java:50)
  at androidx.fragment.app.FragmentState.instantiate (FragmentState.java:80)
  at androidx.fragment.app.FragmentManagerImpl.restoreAllState (FragmentManager.java:3109)
  at androidx.fragment.app.FragmentController.restoreAllState (FragmentController.java:158)
  at androidx.fragment.app.FragmentActivity.onCreate (FragmentActivity.java:344)
  at androidx.appcompat.app.AppCompatActivity.onCreate (AppCompatActivity.java:85)
  at com.autotask.jbarra.kotlinmvvm.MainActivity.onCreate (MainActivity.kt:102)
  at android.app.Activity.performCreate (Activity.java:7326)
  at android.app.Activity.performCreate (Activity.java:7317)
  at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1271)
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3066)

Caused by: java.lang.NoSuchMethodException: 
  at java.lang.Class.getConstructor0 (Class.java:2328)
  at java.lang.Class.getConstructor (Class.java:1725)
  at androidx.fragment.app.Fragment.instantiate (Fragment.java:443)

问题是,主要活动的第 102 行没有什么特别的

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState) //This is line 102

是什么原因造成的?为什么 oncreate 没有抛出这样的方法?它发生在一些用户的设备上,我无法重现它。

【问题讨论】:

  • 分享你的 xml 布局
  • 你解决了吗? 0-arg 构造函数根本没有帮助我。对我来说,它看起来像是 Proguard。在下面检查我的答案。

标签: java android android-fragments kotlin


【解决方案1】:

活动正在从实例状态包中恢复。部分还原操作正在重新创建其片段。

您的活动有一个片段,而片段类没有框架所需的 0-arg 构造函数。

【讨论】:

  • “不保留活动”开发人员设置强制活动在转到另一个活动时保存状态,在返回时触发恢复。
  • @laalto 如何解决这个问题?
  • @ch3tanz 移除显式构造函数或添加一个 0-arg 构造函数。
  • @laalto 我正在使用带有 androidx 库的片段导航图
  • 没有人有完整的解释以及如何解决它?我有 0 arg 构造函数,但仍然出现此错误...
【解决方案2】:

我也有同样的问题。其他答案没有帮助。

对我来说,它看起来像是 Proguard。这就解释了为什么它只发生在生产/发布版本中,以及为什么我在调试时无法重现它。

如果您遇到 OP 问题,请尝试以下操作:

  1. 构建经过混淆的 .apk。我使用的是已签名的,我将其发布到应用商店...
  2. 在您设备的开发者选项中启用“不保留活动”。
  3. 在您的设备中安装 .apk 并打开崩溃并包含 Fragment 的 Activity。
  4. 离开您的应用(最小化/主页按钮/...),然后从最近的应用菜单重新打开它。

它会崩溃吗?然后尝试使用未混淆的调试版本。如果不是,那么它可能是 Proguard。

为了修复它,我做了以下操作:

  1. 在应用模块的根文件夹中创建一个 proguard-rules.pro 文件。
  2. 添加 -keep class * 将 androidx.fragment.app.Fragment{} 扩展至该文件。
  3. 然后,在应用的 build.gradle 中,

添加:

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

在此处查看 Yaroslav Mytkalyk 的答案:Fragment Instantiation crash,它帮助我解决了这个问题,尽管它现在有点过时和过时(例如“runProguard true”已过时)。

至少现在当我执行上述步骤时它不会崩溃。

PS:正如其他答案中提到的,我将 0-arg 构造函数添加到我的片段中,因为这是我的第一次修复尝试。我相信 Proguard 本身就是问题所在,没有必要添加上述构造函数,但我现在无法检验该假设。

【讨论】:

  • 使用此规则,您的所有片段都不会缩小,这不是一个好习惯
  • 是的。但是添加 0-arg 构造函数并没有帮助。如果有人知道的话,我对解决此问题的替代(和适当)方法持开放态度。
【解决方案3】:

我的 Activity 有一个 FragmentPagerAdapter 正在使用已弃用的构造函数。 我变了

class MyPagerAdapter(
        fragmentManager: FragmentManager,
        private val myActivity: MyActivity
    ) : FragmentPagerAdapter(fragmentManager) // DEPRECATED

class MyPagerAdapter(
        fragmentManager: FragmentManager,
        private val myActivity: MyActivity
    ) : FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)

似乎已经解决了问题

【讨论】:

  • FragmentStatePagerAdapter 是我的问题,在更改为 FragmentPagerAdapter 后对我有用。谢谢。
【解决方案4】:

经过一番搜索,我终于解决了这个问题。你必须检查 3 件事。

  1. 您应该在片段中有一个 0-arg 构造函数,最佳做法是执行如下操作
  2. 如果你在调用者中使用回调,你必须检查getContext是否为null(否则你会得到一个NullPointerException)
  3. 不要忘记在屏幕方向改变时测试案例,这将允许您重现由于恢复片段状态而导致的一些潜在问题

示例代码示例:

    public class MyDialogFragment extends DialogFragment{
     private String id;

     public static MyDialogFragment newInstance(String id) {
        MyDialogFragment f = new MyDialogFragment ();

        Bundle args = new Bundle();
        if(id!= null){
            args.putString("id", id);
        }
        f.setArguments(args);

        return f;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(savedInstanceState != null){
            id= savedInstanceState.getString("id");
        }
    }
    }

【讨论】:

    【解决方案5】:

    如前所述,问题是片段中缺少 0-arg 构造函数。
    在我的例子中,构造函数是通过发布变体的代码收缩从DialogFragment 中删除的。

    要重现崩溃,请使用 minifyEnabled true 构建应用,弹出 DialogFragment 并旋转设备屏幕。

    保留 0-arg 构造函数的简单解决方案是添加 @Keep 注释:

    public class MyDialogFragment extends DialogFragment {
        @Keep
        public MyDialogFragment() {}
    }
    

    【讨论】:

      【解决方案6】:

      由于缺少片段的零参数构造函数,系统无法恢复片段。

      向所有片段添加零参数构造函数将解决错误。

      public YourFragment() {}
      

      【讨论】:

        猜你喜欢
        • 2013-03-12
        • 2013-11-23
        • 2015-02-25
        • 1970-01-01
        • 1970-01-01
        • 2013-08-04
        • 2020-10-21
        • 2017-03-26
        • 1970-01-01
        相关资源
        最近更新 更多