简体   繁体   中英

How to catch RuntimeException thrown within a Fragment

I have an Android Fragment embedded in my app. During deployment I have had certain Android subsystems throw undocumented RuntimeException instances. Annoying, but I figured I would just catch them in the Activity housing the Fragment . Unfortunately, I haven't been too successful at this so far.

My layout XML is as follows:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <fragment android:name="com.my.ui.MyFragment"
        android:id="@+id/my_frag"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

To simulate a RuntimeException , I added this to MyFragment.onResume :

public void onResume() {
    super.onResume();
    ...
    throw new RuntimeException("Boom.");
}

To try to catch it in the Activity, I thought maybe it happens during the layout inflation process so I surrounded the setContentView call in a try-catch:

public void onCreate() {
    super.onCreate();
    try {
        setContentView(R.layout.base_layout);
    } catch(Exception e) {
        Log.e(TAG, e.getMessage());
    }
}

EDIT After I wrote this question, thought to try catching something from super.onResume() in MyActivity.onResume like this:

public void onResume() {
        try {
            super.onResume();
            ...
        } catch(Exception e) {
            Log.d(TAG, "I caught something baby!!!");
            Log.e(TAG, e.getMessage());
        }
    }

Unfortunately, no dice... it appears the Android framework maybe getting to it before my Activity can. Below is the relevant LogCat:

02-06 16:19:36.908: E/AndroidRuntime(29033): FATAL EXCEPTION: main
02-06 16:19:36.908: E/AndroidRuntime(29033): Process: com.my.myactivity, PID: 29033
02-06 16:19:36.908: E/AndroidRuntime(29033): java.lang.RuntimeException: Unable to resume activity {com.my.myactivity/com.my.myactivity.MyActivity}: java.lang.RuntimeException: Boom.
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2788)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2817)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2250)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.ActivityThread.access$800(ActivityThread.java:135)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.os.Handler.dispatchMessage(Handler.java:102)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.os.Looper.loop(Looper.java:136)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.ActivityThread.main(ActivityThread.java:5017)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at java.lang.reflect.Method.invokeNative(Native Method)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at java.lang.reflect.Method.invoke(Method.java:515)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at dalvik.system.NativeStart.main(Native Method)
02-06 16:19:36.908: E/AndroidRuntime(29033): Caused by: java.lang.RuntimeException: Boom.
02-06 16:19:36.908: E/AndroidRuntime(29033):    at com.my.ui.MyFragment.onResume(MyFragment.java:97)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.Fragment.performResume(Fragment.java:1743)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:924)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1044)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:1863)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.Activity.performResume(Activity.java:5320)
02-06 16:19:36.908: E/AndroidRuntime(29033):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2778)
02-06 16:19:36.908: E/AndroidRuntime(29033):    ... 12 more

Is it possible to catch exceptions thrown by a fragment during one of its lifecycle phases, or do I need to catch it and send the exception via Handler or custom callback interface?

Whoever is calling onResume can catch this exception.
You cannot just catch it in another unrelated method like this.

Think what happens on the call stack.

Only if the call to onCreate causes the call to onResume
(directly or indirectly), then you can catch it in onCreate
provided no one else caught it already.

So if you have this chain of calls:
some code -> onCreate -> A -> B -> C -> ... -> D -> onResume
and methods D, ... , C, B, A do not catch the exception,
then you can catch it in onCreate.

I am not familiar with Android so answering a bit in general.

I seriously doubt you have this chain of calls in Android.
I guess the framework is calling both methods independently.
I mean just looking at the method names, I guess it doesn't
make sense to have this call chain which I wrote above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM