用于onCreate的java.lang.NoSuchMethodException

时间:2019-06-19 13:32:59

标签: java android android-fragments kotlin

我在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不会抛出这种方法?它正在少数用户的设备上发生,而我却无法复制它。

6 个答案:

答案 0 :(得分:2)

活动正在从实例状态束中恢复。恢复操作的一部分是重新创建其片段。

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

答案 1 :(得分:2)

“我的活动”中有一个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)

似乎已解决问题

答案 2 :(得分:2)

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

  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");
        }
    }
    }

答案 3 :(得分:2)

我遇到了同样的问题。其他答案没有帮助。

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

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

  1. 构建模糊的.apk。我使用了签名的,然后发布到应用商店...
  2. 在设备的开发人员选项中启用“不保留活动”。
  3. 在设备中安装.apk,然后打开崩溃并包含Fragment的活动。
  4. 保留您的应用程序(“最小化” /“主页”按钮/ ...),然后从最近的应用程序菜单中重新打开它。

它崩溃了吗?然后,使用无混淆的调试版本进行尝试。如果没有,则可能是Proguard。

要解决此问题,我执行了以下操作:

  1. 在应用模块的根文件夹中创建一个proguard-rules.pro文件。
  2. 添加-keep类*将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就是问题所在,没有必要添加上述构造函数,但是我现在无法检验该假设。

答案 4 :(得分:0)

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

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

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

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

答案 5 :(得分:-1)

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

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

public YourFragment() {}