[英]java.lang.NoSuchMethodException for onCreate
我在 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 沒有拋出這樣的方法? 它發生在一些用戶的設備上,我無法重現它。
活動正在從實例狀態包中恢復。 還原操作的一部分是重新創建其片段。
您的活動有一個片段,片段類沒有框架所需的 0-arg 構造函數。
我有同樣的問題。 其他答案沒有幫助。
對我來說,它看起來像是 Proguard。 這解釋了為什么它只發生在生產/發布版本中,以及為什么我在調試時無法重現它。
如果您遇到 OP 的問題,請嘗試以下操作:
它會崩潰嗎? 然后使用未混淆的調試版本嘗試它。 如果沒有,那么它可能是 Proguard。
為了修復它,我做了以下事情:
添加:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
請在此處查看 Yaroslav Mytkalyk 的回答: Fragment Instantiation crash ,它幫助我解決了這個問題,盡管它現在有點舊且過時了(例如,“runProguard true”已過時)。
至少現在當我執行上述步驟時它不會崩潰。
PS:正如其他答案中提到的那樣,我將 0-arg 構造函數添加到我的片段中,因為這是我的第一次修復嘗試。 我相信 Proguard 本身就是問題所在,並且沒有必要添加所述構造函數,但我現在無法測試該假設。
我的 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)
似乎已經解決了問題
經過一番搜索,我終於解決了這個問題。 你必須檢查3件事。
null
(否則你會得到一個 NullPointerException)示例代碼示例:
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");
}
}
}
如前所述,問題在於 Fragment 中缺少 0-arg 構造函數。
在我的情況下,構造函數是通過發布變體的代碼收縮從DialogFragment
中刪除的。
要重現崩潰,請使用minifyEnabled true
構建應用程序,彈出 DialogFragment 並旋轉設備屏幕。
保留 0-arg 構造函數的一個簡單解決方案是添加@Keep
注釋:
public class MyDialogFragment extends DialogFragment {
@Keep
public MyDialogFragment() {}
}
對於 Kotlin,這里有一個有問題的構造函數語法示例以及如何重寫它。 第一行是構造函數,它有一個參數。 當應用程序關閉並且 Android 嘗試恢復它時,這會導致getConstructor0
崩潰:
open class MyFragment(parent: MyClass) : Fragment() {
var parent = parent
}
以下重寫避免了崩潰。 第一行是零參數構造函數,第二行是自定義構造函數:
open class MyFragment : Fragment() {
constructor(parent: MyClass): this() {
this.parent = parent
}
lateinit var parent: MyClass
}
當您像MyFragment(parent)
這樣實例化類時,它的工作方式與以前相同。 但是,當 Android 恢復應用程序時,它會調用MyFragment()
,因此您需要考慮使用未初始化變量運行的類。 如果需要,您可以檢查this::parent.isInitialized
。
與其將問題描述為“你需要一個 0 參數的構造函數”,我更容易理解為“你不能在創建片段時傳遞參數(除非你准備好不設置該參數)。
這需要一段時間才能理解,因為我的大部分片段類都沒有參數,而且我看不出我做錯了什么。 但是我有一個子片段的一個子片段,我已經設置了一個子片段來進行爭論。 該類名稱未顯示在 Google Play 控制台崩潰日志中,但當我按照此答案中的說明重現問題時,它確實顯示在 Android Studio 控制台中,然后這終於變得清晰了。
Google Play 崩潰日志只顯示了這個:
Caused by java.lang.NoSuchMethodException:
但是 Android Studio 控制台顯示了這一點,崩潰發生在 FormList 類中:
Caused by: java.lang.NoSuchMethodException: com.arlomedia.bandhelper.superclasses.FormList.<init> []
更改您的設計以完全避免構造函數參數可能是適合您的情況的更好解決方案。 在我的例子中,變量是一個對象,所以我無法保存它並從包中恢復它。 我不想讓它成為可選的,因為它總是在應用程序正常運行時設置。 而且我的應用程序無論如何都會在重新啟動后重新加載其界面,所以我只需要在不崩潰的情況下完成 Android 的恢復嘗試。
由於缺少片段的零參數構造函數,系統無法恢復片段。
向所有片段添加零參數構造函數將解決錯誤。
public YourFragment() {}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.