2

I have an activity - MainActivity, where I initialize member variable in onCreate(...) method. This variable is then used in onStart() and onStop() methods.

Pretty simple, huh? Now the issue is, that from my users, I started to get NullPointerException crash reports, which happens in onStop() method.

I've been extensively searching for the cause, and I understand that static variables may become null when android decides to free up memory, however I couldn't find a case with member variable, which is initialized in onCreate(). The code is following:

public class MainActivity extends ActionBarActivity implements ActionBar.TabListener, SharedPreferences.OnSharedPreferenceChangeListener {
private MySvc mySvc;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);     
    mySvc = DI.i().getMySvc();
    ...
}

@Override
protected void onStart() {
    super.onStart();
    mySvc.start();
}

...

@Override
protected void onStop() {
    super.onStop();
    //here I get NPE
    mySvc.stop();
}
}

}

To make things even more mysterious, I started to get this crash reports only from certain versions of app, however the old versions have same behavior in onStart() and onStop().

I will be grateful for any hint.

Edit:

  • DI.i().getMySvc(); never returns null, its done according to singleton pattern.
  • MySvc is a POJO, which is instantiated in DI class
Tomas Bartalos
  • 1,256
  • 12
  • 29

2 Answers2

1

I need to appologize, I've found out that the issue is caused by our code. From certain version we added internet connection check to onCreate() method like this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);     
    if (!isInternetConnectionPresent()) {
        return;
    }
    mySvc = DI.i().getMySvc();
...
}

So if users were offline, they got NPE, since variables were never initialized, however onStop() was called. I think the root cause is wrong approach to error handling. What I would like to achieve is to be able to throw exceptions from activity, and have generic handlers, which would be able to handle those exceptions. So in this case I would throw NoInternetConnectionException and a handler would display a meaningful dialog to the user. Also I wonder if other lifecycle methods are called when an exception is thrown.

Tomas Bartalos
  • 1,256
  • 12
  • 29
-1

Depending on what MySvc is, android VM may choose to GC it as it needs. The best approach with android is to first check for null, instantiate it again if needed, and then do what you want. Works for me all the time and no performance issues.

Nazgul
  • 1,892
  • 1
  • 11
  • 15
  • 1
    The VM will only GC unreachable objects. The VM won't GC an object if there is a reference which can reach it. The VM certainly won't randomly set references in our code to `null`. – Code-Apprentice Sep 08 '14 at 09:58
  • True, this is exactly the reason why I'm confused here. I've temporarily fixed the issue with: DI.i().getMySvc().stop() in onStop() method. However I can't count with instance variables being null at any time !? – Tomas Bartalos Sep 08 '14 at 10:24
  • Yes that is true and I know that. But the call in the query code says DI.i().getMySvc(); I for sure don't know what that does. So Code-Apprentice if also don't know then please remove the down vote. I clearly said 'Depending on what MySvc is' – Nazgul Sep 08 '14 at 10:28