Android app force closes when setting a CursorAdapter

user71607 picture user71607 · Jan 15, 2014 · Viewed 15k times · Source

I am following a video tutorial on Udemy.com from here

Everything has gone well up until messing with SQL. Now, I'm not a total SQL newbie, I actually took a college course on it using SQL from the command line, but I'm not a pro either. The app does not error out when compiled, but gives an immediate force close, and my logcat points me to lvCountries.setAdapter(adapter). The part that interests me is "Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference". So would my adapter be the null object, or lvCountries? My last lead is when I instantiate countries with db.query(). Android Studio gives me a warning saying that it might produce a NullPointerExecption. Thanks to everyone in advance.

01-15 08:39:59.560    9056-9056/com.example.sql E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.sql, PID: 9056
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sql/com.example.sql.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
        at android.app.ActivityThread.access$800(ActivityThread.java:135)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5017)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
        at com.example.sql.MainActivity.onCreate(MainActivity.java:44)
        at android.app.Activity.performCreate(Activity.java:5231)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)

MainActivity.java

package com.example.sql;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.provider.BaseColumns;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

public class MainActivity extends ActionBarActivity {

    private CountryDB countryDatabase = null;
    private Cursor countries = null;
    private ListView lvCountries = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Create the database helper
        SQLiteDatabase.CursorFactory factory = null;
        countryDatabase = new CountryDB(this, "countryDB", factory);

        String[] columnNames = {"Name", "Pop", "Area", BaseColumns._ID};
        lvCountries = (ListView) findViewById(R.id.lvCountries);

        int[] targetLayoutIDs = {R.id.textName, R.id.textPop, R.id.textArea};

        SQLiteDatabase db = countryDatabase.getReadableDatabase();
        countries = db.query("countries", columnNames, null, null, null, null, null);
        CursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.country_item,
                countries, columnNames, targetLayoutIDs, 0);
        lvCountries.setAdapter(adapter);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment())
                    .commit();
        }
    }


    public void onPause() {
        super.onPause();
        countryDatabase.close();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            return rootView;
        }
    }

}

country_item.xml

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

    <TextView
        android:id="@+id/textName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <LinearLayout 
        android:id="@+id/subItem"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/popLabel" />

        <TextView
            android:id="@+id/textPop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceSmall" />

        <TextView 
            android:layout_width= "5dp" 
            android:layout_height="wrap_content" 
            android:text="@string/space" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/areaLabel" />

        <TextView
            android:id="@+id/textArea"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceSmall" />

        <TextView 
            android:layout_width= "5dp" 
            android:layout_height="wrap_content" 
            android:text="@string/space" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/areaDescriptor" />

    </LinearLayout>

</LinearLayout>

Here is the rest of my code in Android Studio format if you're interested. http://www.mediafire.com/download/zu0x71ysl67b779/SQLLiteAndListViews.tar.gz

Answer

Entreco picture Entreco · Jan 15, 2014
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference

Apparently, lvCountries is null which is why this line is crashing:

lvCountries.setAdapter(adapter);

Looking in your code, it seems that you are not retrieving the correct view:

lvCountries = (ListView) findViewById(R.id.lvCountries);

Make sure that there exists a ListView in your R.layout.activity_main with

<ListView
    android:id="@+id/lvCountries"
    ... other parameters here
/>