简体   繁体   中英

App crashes on screen rotation when trying to find menu item

I am using a collapsingToolbarLayout in my application and as long as the menu is not collapsed there is no problem when rotating the phone. But when the menu is collapsed and only the original toolbar is showing the app crashes. The thing is, when only the original toolbar is showing a clickable item appears and disappears when the collapsing toolbar is shown. When rotating the phone, the application does not find this item. How can I solve this?

The activity where the menu is.

private Menu menu;
protected void onCreate(Bundle savedInstanceState) { 
    ...
    AppBarLayout mAppBarLayout = findViewById(R.id.appBarLayout2);
    mAppBarLayout.addOnOffsetChangedListener(new 
    AppBarLayout.OnOffsetChangedListener() {

            int scrollRange = -1;

            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int 
            verticalOffset) {
                if (scrollRange == -1) {
                    scrollRange = appBarLayout.getTotalScrollRange();
                }
                if (scrollRange + verticalOffset == 0) {
                    isShow = true;
                    showOption();
                } else if (isShow) {
                    isShow = false;
                    hideOption();
                }
            }
        });

    }

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        this.menu = menu;
        getMenuInflater().inflate(R.menu.menu_scrolling, menu);
        hideOption();
        return true;
    }

private void hideOption() {
        MenuItem item = menu.findItem(R.id.action_info);
        item.setVisible(false);
    }

    private void showOption() {
        MenuItem item = menu.findItem(R.id.action_info);
        item.setVisible(true);
    }

The relevant code in xml-file:

<android.support.design.widget.AppBarLayout
        android:id="@+id/appBarLayout2"
        android:layout_width="match_parent"
        android:layout_height="128dp"
        android:theme="@style/AppTheme.Base"
        app:layout_constraintTop_toTopOf="@+id/nestedScrollView">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsTool"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/colorSecondary"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleGravity="bottom|center"
            app:expandedTitleMargin="16dp"
            app:expandedTitleTextAppearance="@style/TextAppearance.AppCompat.Display2"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:title="@string/title_expenses">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:navigationIcon="@drawable/ic_action_exit"
                app:title="@string/title_expenses"
                app:titleTextColor="@android:color/background_light" />

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

The menu_Scrolling.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.journaldev.collapsingtoolbarlayout.ScrollingActivity">

    <item
        android:id="@+id/action_info"
        android:icon="@drawable/ic_action_add"
        android:orderInCategory="200"
        android:title="Add"
        app:showAsAction="ifRoom" />

</menu>

This is the error message:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.korneliapalm.android.samboappen/com.korneliapalm.android.samboappen.MoneyListActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'android.view.MenuItem android.view.Menu.findItem(int)' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3114)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3257)
        at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5039)
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4948)
        at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
        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:1948)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7050)
        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:965)
     Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'android.view.MenuItem android.view.Menu.findItem(int)' on a null object reference
        at com.korneliapalm.android.samboappen.MoneyListActivity.showOption(MoneyListActivity.java:163)
        at com.korneliapalm.android.samboappen.MoneyListActivity.onCreate(MoneyListActivity.java:51)
        at android.app.Activity.performCreate(Activity.java:7327)
        at android.app.Activity.performCreate(Activity.java:7318)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3094)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3257) 
        at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5039) 
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4948) 
        at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69) 
        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:1948) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7050) 
        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:965) 

The problem is that in onCreate you are calling the methods hideOption() and showOption() . However, oncreate is called before onCreateOptionsMenu which is where you are inflating the menu view. So calling menu.findItem(R.id.action_info); triggers a null pointer.

getMenuInflater().inflate(R.menu.menu_scrolling, menu);

You need to ensure that the menu view is inflated before you call these two methods in onCreate.

private void hideOption() {
    if (menu == null) return;
    MenuItem item = menu.findItem(R.id.action_info);
    item.setVisible(false);
}

private void showOption() {
    if (menu == null) return;
    MenuItem item = menu.findItem(R.id.action_info);
    item.setVisible(true);
}

Activity:

When orientation change occurs,android restarts the running Activity ( onDestroy() is called, followed by onCreate()). If you want to handle inside activity,you cant use: in manifest file for particular activity.

For API 12 and below:

android:configChanges="orientation"

if you are targeting API 13 or above

android:configChanges="orientation|screenSize"

You have not handled orientations in your code. You should try to handle them. The reason for your crash is that when you rotate your screen following event happens:

  1. Activity gets destroyed.
  2. Activity gets re-created.
  3. AppBarLayout's offset gets changed and the method onOffsetChanged is called.
  4. if (scrollRange + verticalOffset == 0) { condition gets true and showOption(); method is called.
  5. Because the Activity is being re-created, the menu item that is used in showOption(); method is null on the line MenuItem item = menu.findItem(R.id.action_info);
  6. Because the item is null, the code item.setVisible(true); produces a runtime crash of Null Pointer Exception .

The proper way of handling orientations is to implement the following method in your Activity code:

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)

    // Checks the orientation of the screen
    if (newConfig.orientation === Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show()
    } else if (newConfig.orientation === Configuration.ORIENTATION_PORTRAIT) {
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show()
    }
}

As a pre-cautionary measure, you can add null checks for avoiding the crashes temporarily like this:

private void hideOption() {
    MenuItem item = menu.findItem(R.id.action_info);
    if (item != null) {
        item.setVisible(false);
    } else {
        Log.e("Your Class", "hideOption() was called, but menu item was null");
    }
}

private void showOption() {
    MenuItem item = menu.findItem(R.id.action_info);
    if (item != null) {
        item.setVisible(true);
    } else {
        Log.e("Your Class", "showOption() was called, but menu item was null");
    }
}

I hope this helps.

Reference link: https://developer.android.com/guide/topics/resources/runtime-changes

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