Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have come across a bug that I cannot understand for the life of me. I have a listener the makes a webservice call and populates static arraylists from two other classes practiceRoundListActivity and qualifierRoundListActivity. So in the code below, within the foreach loop I have two conditionals which decides which arraylist the event will be inserted. The first condition "praciticeRoundListActivity.values..." works fine, but the call to "qualifierRoundListActivity.values..." does not work and I get a null pointer exception.

    public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
    if (arg2 != 0) {
        String name = (String) arg0.getItemAtPosition(arg2);
        Log.d(TAG, name);
        Team team = SpectatorActivity.map2.get(name);
        Log.d(TAG, team.getGSID());
        String url = "http://qualifiers.golfstat.com/webservices/remote.cfc?method=getEventsByGSID&GSID=";
        url += team.getGSID();
        wt.execute(url, team);
        //practiceRoundListActivity.values = new ArrayList<String>();
        //qualifierRoundListActivity.values2 = new ArrayList<String>();
        for(Event event : team.getEvents()) {
            if(event.getType() == 'p') {
                Log.d(TAG, "PR found");
                practiceRoundListActivity.values.add(event.getEventDescription() + " " + event.getTournamentDescription());
            } else if(event.getType() == 'q') {
                Log.d(TAG, "QR found");
                // //HERE IS THE BUG qualifierRoundListActivity.values.add(event.getEventDescription() + " " + event.getTournamentDescription());
            }
        }
        tabHost.setCurrentTab(1);
        tabHost.setVisibility(0);
    }
}

Being list activities, practiceRoundListActivity and qualifierRoundListActivity are attached to an arrayadapter to be displayed. I have exhausted every idea to learn something, anything about why this is happening. Most recently, since practiceRound... and qualifierRound... are so similar I copied the code for practiceRound... class into qualifierRound... and changed all the necessary names to quailifierRound...(I know these class names are annoyingly long). Thank you in advance for any help.

public class qualifierRoundListActivity extends ListActivity {

static ListView listView;
ArrayAdapter<String> adapter;
public static ArrayList<String> values;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.round_list);

    listView = getListView();
    values = new ArrayList<String>();
    adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, values);
    listView.setAdapter(adapter);
    listView.setOnItemClickListener(new OnItemClickListener() {

        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {
            // TODO Auto-generated method stub
            Intent intent = new Intent(getApplicationContext(), LeaderBoardActivity.class);
            startActivity(intent);
        }

    });
}

public static void setMultipleChoice() {
    listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}

@Override
public void onPause() {
    super.onPause();
    listView.setOnItemLongClickListener(null);
}
}

Logcat: Line 154 is the "qlualifierRoundListActivity.values.add(..." line.

03-20 23:05:59.272: E/AndroidRuntime(2392): FATAL EXCEPTION: main
03-20 23:05:59.272: E/AndroidRuntime(2392): java.lang.NullPointerException
03-20 23:05:59.272: E/AndroidRuntime(2392):     at com.gstat.activities.SpectatorActivity.onItemSelected(SpectatorActivity.java:154)
03-20 23:05:59.272: E/AndroidRuntime(2392):     at android.widget.AdapterView.fireOnSelected(AdapterView.java:871)
03-20 23:05:59.272: E/AndroidRuntime(2392):     at android.widget.AdapterView.access$200(AdapterView.java:42)
03-20 23:05:59.272: E/AndroidRuntime(2392):     at android.widget.AdapterView$SelectionNotifier.run(AdapterView.java:837)
03-20 23:05:59.272: E/AndroidRuntime(2392):     at android.os.Handler.handleCallback(Handler.java:587)
03-20 23:05:59.272: E/AndroidRuntime(2392):     at android.os.Handler.dispatchMessage(Handler.java:92)
03-20 23:05:59.272: E/AndroidRuntime(2392):     at android.os.Looper.loop(Looper.java:123)
03-20 23:05:59.272: E/AndroidRuntime(2392):     at android.app.ActivityThread.main(ActivityThread.java:3683)
03-20 23:05:59.272: E/AndroidRuntime(2392):     at java.lang.reflect.Method.invokeNative(Native Method)
03-20 23:05:59.272: E/AndroidRuntime(2392):     at java.lang.reflect.Method.invoke(Method.java:507)
03-20 23:05:59.272: E/AndroidRuntime(2392):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
03-20 23:05:59.272: E/AndroidRuntime(2392):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
03-20 23:05:59.272: E/AndroidRuntime(2392):     at dalvik.system.NativeStart.main(Native Method)

So I have the qualifierRoundListActivity displayed in a tab and below is how I start it from my main class.

    public void setupTab(final View view, final String tag) {
    View tabView = createTabView(tabHost.getContext(), tag);
    TabSpec setContent = tabHost.newTabSpec(tag).setIndicator(tabView);
    Intent intent;
    if(tag == "Practice Rounds") {
        intent = new Intent(this, practiceRoundListActivity.class);
        setContent.setContent(intent);
    }
    else {
        intent = new Intent(this, qualifierRoundListActivity.class);
        setContent.setContent(intent);
    }
    tabHost.addTab(setContent);
}

private static View createTabView(final Context context, final String text) {
    View view = LayoutInflater.from(context).inflate(R.layout.tabs_small, null);
    TextView textView = (TextView) view.findViewById(R.id.tabsText);
    textView.setText(text);
    return view;
}

When I added a static method inside of the qualifier... class:

public static void add(String event) {
    values.add(event);
}

I received a null pointer exception on the values.add(event) line.

share|improve this question
can we see where you initialize`qualifierRoundListActivity.values`? If that is the line then it looks like that may be null – codeMagic Apr 5 at 23:07

2 Answers

Try to put values = new ArrayList(); before the setContentView

share|improve this answer
I can't see how this would help at all. – Sky Kelsey Apr 6 at 0:25

Static data that is initialized with an Activity will be deleted when that Activity ends its lifecycle and is garbage collected. You should not assume that it will be there.

Instead of accessing the data directly, query for it within a static method. That method will first check to see if the static data is null, and if so, it will repopulate it, before returning it.

The Android Activity lifecycle is confusing, and you have probably developed some reasonable, but incorrect assumptions about how Activities behave.

A solution for you would probably be to persist this data (example: in a SharedPreferences), and not bother with storing it as static data unless absolutely necessary.

share|improve this answer
The items selected method also bound to the life cycle of the activity ... – Chen Kinnrot Apr 5 at 23:09
Ok, I think I understand what you're saying but I'm not sure where the activity would be destroyed. I will try SharedPreferences. – Pat Herrod Apr 5 at 23:44
Wait, why would it work for practiceRoundListActivity but not qualifierRoun...? – Pat Herrod Apr 5 at 23:57
@PatHerrod Only one Activity is running at any given time. Once an Activity stops running, it can be garbage collected at any time. If you were to place a log statement in your onDestroy(), onCreate(), and finalize() methods that printed out this.hashcode(), you will be able to see the lifecycle in action. Why is it working from one Activity and not the other? Probably because practiveRoundListActivity is actually the one running, and qualifierRoundListActivity has been stopped and garbage colleccted? – Sky Kelsey Apr 6 at 0:25

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.