5

whenever I create my activity initially, everything goes fine as I am able to inflate my layouts correctly. However, the issue is whenever I switch to using another app, then go back to my own app, I get an error saying that the TabLayout is null, causing my app to crash. If I switch to another app for a few minutes, my DrawerLayout is null, also causing my app to crash.

If I understand the Android Life Cycle correctly, I realize that the activity is recreated when it goes from background to foreground, and the onCreate method is called again as referenced from this: Android activity life cycle - what are all these methods for?. However, I don't understand why when the app starts, everything works fine, but when I go into the background, either the TabLayout or the DrawerLayout is set to null. Here is my attempt:

news_feed.java:

private static DrawerLayout drawer;
private static TabLayout tabLayout;

public class news_feed extends BatchAppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_feed);
        drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //Listen for navigation events
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close){

        public void onDrawerOpened(View view) {
            super.onDrawerOpened(view);
        }

        /** Called when a drawer has settled in a completely closed state. */
        public void onDrawerClosed(View view) {
            super.onDrawerClosed(view);
        }
    };
        System.out.println("news_feed: toolbar: " + toolbar);
        System.out.println("news_feed: Drawer: " + drawer);
        System.out.println("news_feed: toggle: " + toggle);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        System.out.println("news_feed: Tab Layout: " + tabLayout);
        tabLayout.addTab(tabLayout.newTab().setText("First"));
        tabLayout.addTab(tabLayout.newTab().setText("Second"));
        tabLayout.addTab(tabLayout.newTab().setText("Third"));
        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
    }
}

news_feed.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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" android:id="@+id/drawer_layout"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:fitsSystemWindows="true" tools:openDrawer="start">

    <include layout="@layout/app_bar_news_feed" android:layout_width="match_parent"
        android:layout_height="match_parent" android:id="@+id/app_bar_main" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <include
                layout="@layout/nav_header_friends_list"
                android:id="@+id/navigation_header"/>

            <ListView
                android:id="@+id/friends_list"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"></ListView>

        </LinearLayout>

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

</android.support.v4.widget.DrawerLayout>

app_bar_news_feed.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    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" android:layout_width="match_parent"
    android:layout_height="match_parent" android:fitsSystemWindows="true"
    tools:context=".news_feed">

    <RelativeLayout
        android:id="@+id/main_layout"
        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"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout android:layout_height="wrap_content"
        android:layout_width="match_parent" android:theme="@style/AppTheme.AppBarOverlay" android:id="@+id/app_bar">

        <android.support.v7.widget.Toolbar android:id="@+id/toolbar"
            android:layout_width="match_parent" android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" />

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

    <!-- <include layout="@layout/content_news_feed" /> -->

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/app_bar"
        android:background="?attr/colorPrimary"
        android:elevation="6dp"
        android:minHeight="?attr/actionBarSize"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:layout_below="@id/tab_layout"/>

    </RelativeLayout>

    <android.support.design.widget.FloatingActionButton android:id="@+id/fab"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email" />

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

I made sure that the findViewById's are all referencing the correct id's, but I can't seem to figure what is going wrong. It's strange: if I quickly switch from app -> another app -> app, then the TabLayout is null. If I switch from app -> another app -> wait a few minutes -> app, then DrawerLayout is null. I have no idea why this is occuring! Any help would be appreciated.

Edit: The app crashes on the onCreate method of my activity. Moreover, I have provided a stacktrace: as followed here:

03-16 09:31:21.116 25852-25852/com.test.tabs.tabs I/System.out: news_feed: toolbar: android.support.v7.widget.Toolbar{380bcc25 V.E..... ......ID 0,0-0,0 #7f0d009c app:id/toolbar} 03-16 09:31:21.116 25852-25852/com.test.tabs.tabs I/System.out: news_feed: Drawer: android.support.v4.widget.DrawerLayout{3ed761fa VFE..... ......I. 0,0-0,0 #7f0d0095 app:id/drawer_layout} 03-16 09:31:21.116 25852-25852/com.test.tabs.tabs I/System.out: news_feed: toggle: com.test.tabs.tabs.com.tabs.activity.news_feed$1@22eb13ab 03-16 09:31:21.116 25852-25852/com.test.tabs.tabs I/System.out: news_feed: Tab Layout: null 03-16 09:31:21.116 25852-25852/com.test.tabs.tabs E/AndroidRuntime: FATAL EXCEPTION: main Process: com.test.tabs.tabs, PID: 25852 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.tabs.tabs/com.test.tabs.tabs.com.tabs.activity.news_feed}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.support.design.widget.TabLayout$Tab android.support.design.widget.TabLayout.newTab()' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2661) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) at android.app.ActivityThread.access$900(ActivityThread.java:172) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:145) at android.app.ActivityThread.main(ActivityThread.java:5835) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.support.design.widget.TabLayout$Tab android.support.design.widget.TabLayout.newTab()' on a null object reference at com.test.tabs.tabs.com.tabs.activity.news_feed.onCreate(news_feed.java:174) at android.app.Activity.performCreate(Activity.java:6221) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2614) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)  at android.app.ActivityThread.access$900(ActivityThread.java:172)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:145)  at android.app.ActivityThread.main(ActivityThread.java:5835)  at java.lang.reflect.Method.invoke(Native Method)  at java.lang.reflect.Method.invoke(Method.java:372)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 

Edit: Included BatchAppCompatActivity class:

public class BatchAppCompatActivity extends AppCompatActivity {
    @Override
    protected void onStart()
    {
        super.onStart();

        Batch.onStart(this);
    }

    @Override
    protected void onStop()
    {
        Batch.onStop(this);

        super.onStop();
    }

    @Override
    protected void onDestroy()
    {
        Batch.onDestroy(this);

        super.onDestroy();
    }

    @Override
    protected void onNewIntent(Intent intent)
    {
        Batch.onNewIntent(this, intent);

        super.onNewIntent(intent);
    }
}
Community
  • 1
  • 1
user1871869
  • 3,317
  • 13
  • 56
  • 106
  • Don't know if it's related to your error, but the call to `toggle.syncState();` should be done in the `onPostCreate()` method of your `Activity` as the doc says [Documentation](http://developer.android.com/intl/es/reference/android/support/v7/app/ActionBarDrawerToggle.html) – SekthDroid Mar 15 '16 at 09:05
  • According to your code you are not saving any references to your `DrawerLayout` or `TabLayout`. How do you access those later outside the `onCreate` method?. Again it's not true that Activity recreate and `onCreate` is called every time your Activity comes from background to foreground. It happens only if Activity is destroyed. Please post the code where you access `TabLayout` and `DrawerLayout` where it gets null – dishan Mar 15 '16 at 09:44
  • Where does the app crash? In onCreate? If you switch App -> another app -> app onCreate should not be invoked a second time unless you enabled "Do not keep activities" in the developer settings. Please also provide the crash log and the lines of code where it crashes – David Medenjak Mar 15 '16 at 22:58
  • @DavidMedenjak yeah it crashes in the onCreate and I have no idea why it is being called again. I did not enable "Do not keep activities" option either in my code. – user1871869 Mar 15 '16 at 23:07
  • @dishan I have tried to save private static references to `DrawerLayout` or `TabLayout` but I don't get any change. Both are null within the `onCreate` method, and it is called again when I open the application from being in the background. – user1871869 Mar 15 '16 at 23:10
  • 1
    @user1871869 Could you please provide the stacktrace? This code looks perfectly fine. Are you calling `findViewById` also at some other places and do something with those views there? – David Medenjak Mar 15 '16 at 23:11
  • @DavidMedenjak ok i will do so in an few hours. I am still at work but once I get home I can provide that! – user1871869 Mar 15 '16 at 23:13
  • @DavidMedenjak I have included a stacktrace and updated my code. Sorry for the delay. Hope this helps! – user1871869 Mar 16 '16 at 16:37
  • @dishan I have include a stacktrace and updated the code, thank you for your help! – user1871869 Mar 16 '16 at 16:37
  • @user1871869 it could be that you are destroying the activity through changing orientation cause by other application, add this in your activity tag in the manifest to prevent it from destroying, but this is not a good solution: `android:configChanges="orientation|keyboardHidden|screenSize"` – Rod_Algonquin Mar 16 '16 at 19:43
  • @user1871869 Your code seems fine for me. Can't figure out what's going wrong. However I see that your activity extends from BatchAppCompatActivity. Do you have the code of BatchAppCompatActivity too? If so please post that code as well – dishan Mar 17 '16 at 05:37
  • @dishan I have included the code. Does anything jump out or look wrong? – user1871869 Mar 17 '16 at 05:39
  • @user1871869 I still can't figure out anything. Might need more understanding on your code to solve. Anyway can give you few troubleshooting suggestions. If you can change your activities superclass to AppCompatActivity and check if the issue exists. If not the blame is on BatchAppCompatActivity, then you can focus on it – dishan Mar 17 '16 at 05:51
  • @dishan I changed it to superclass AppCompatActivity and unfortunately it didn't work.. :( any other suggestions? I am stuck and I can't seem to figure out how to solve this. – user1871869 Mar 17 '16 at 05:59
  • @user1871869 With the available information I can't figure out anything yet. If you are not using the latest version of the the android design library you can try to update it to the latest and see if it works. Will let you know If I figure out anything else – dishan Mar 17 '16 at 06:18
  • @dishan Do you think it is possible it is because of the `include` of the layout I did? Do you think it's possible that the `news_feed.xml` isn't including the `app_bar_news_feed` layout when I come back from the background? – user1871869 Mar 18 '16 at 06:14
  • @user1871869 I don't think so. In normal conditions it should include. Do you have different versions of `news_feed.xml` `or app_bar_news_feed.xml` for different configurations (portrait, landscape, etc)? – dishan Mar 18 '16 at 06:41
  • @dishan unfortunately I don't have any different versions of news_feed.xml. However, I did try the following: `View layout = (View) findViewById(R.id.app_bar_main);` `tabLayout = (TabLayout) layout.findViewById(R.id.tab_layout);` And that seemed to actually partially recreate the view when the app was in the background... this is very odd haha. Do you have any idea why this would owrk? – user1871869 Mar 18 '16 at 06:44
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/106676/discussion-between-dishan-and-user1871869). – dishan Mar 18 '16 at 06:49
  • @user1871869 I don't. Your problem is strange and I don't have a clue. Why your activity recreate each time when you come from background is also strange. Have your try to add logs to activity's lifecycle events and see which of them are called when you transition from background to foreground. Also you may use http://developer.android.com/tools/help/hierarchy-viewer.html to debug your created view hierarchy. That may give you some clue to solve the problem – dishan Mar 18 '16 at 06:55
  • @dishan well according to the life cycle, if I am not mistaken, after onPause/onStop (basically if the application is in the background or the resources dedicated to the application is killed and needs to be recreated) then onCreate would be called. This is the expected behavior at least from what I read from the app life cycle which makes sense in the context of my application? – user1871869 Mar 18 '16 at 09:05
  • @user1871869 Please take a more closer look at Activity lifecycle. you can find a more readable one here http://developer.android.com/training/basics/activity-lifecycle/starting.html. after `onStop` Activity will be resumed through the `onRestart`->`onStart` flow usually. `onCreate` will called only if activity is destroyed. To this to be happen your Activity should be in background for a considerable time. – dishan Mar 18 '16 at 12:42

1 Answers1

4

Your declaration of the drawer and tabLayout variables seems a bit strange. Unless it's a typo I'm surprised it even works. Something like

public class news_feed extends BatchAppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
    private DrawerLayout drawer;
    private TabLayout tabLayout;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_feed);
        drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //Listen for navigation events
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close){

            public void onDrawerOpened(View view) {
                super.onDrawerOpened(view);
            }

            /** Called when a drawer has settled in a completely closed state. */
            public void onDrawerClosed(View view) {
                super.onDrawerClosed(view);
            }
        };
        System.out.println("news_feed: toolbar: " + toolbar);
        System.out.println("news_feed: Drawer: " + drawer);
        System.out.println("news_feed: toggle: " + toggle);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        System.out.println("news_feed: Tab Layout: " + tabLayout);
        tabLayout.addTab(tabLayout.newTab().setText("First"));
        tabLayout.addTab(tabLayout.newTab().setText("Second"));
        tabLayout.addTab(tabLayout.newTab().setText("Third"));
        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
    }
}

should work assuming toolbar is defined somewhere else in your class.

JohnWowUs
  • 3,053
  • 1
  • 13
  • 20
  • Why is my declaration strange? Do you have any suggestions on how it should be declared? – user1871869 Mar 18 '16 at 09:05
  • @user1871869 drawer and tablayout are declared outside the class (I'm assuming that's a typo unless news_feed is an inner class) and they're declared as private static. Also within your Oncreate method you redeclare tablayout. – JohnWowUs Mar 18 '16 at 09:10
  • @user1871869 did the above solution solved your problem? I am also facing problem similar to you. – Ajay Naredla Aug 03 '17 at 10:35