0

我对此感到困惑。我正在关注书中的一个项目,如果我使用书籍示例文件,它就可以工作。但是,如果我使用我的文件,据我所知是相同的,我得到一个空指针异常。这是下面的文件:

//AddressBook.java
//Main activity for address book app.
package com.deitel.addressbook;

import android.app.ListActivity;
import android.os.Bundle;
import android.os.AsyncTask;
import android.database.Cursor;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.MenuItem;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.util.Log;


public class AddressBook extends ListActivity {

    //string used when logging for debug
    public static final String TAG ="AddressBookBot";

    public static final String ROW_ID = "row_id";  //Intent extra key
    private ListView contactListView;  //the ListActivity's ListView
    private CursorAdapter contactAdapter;  //adapter for ListView

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);  //call super's onCreate
        Log.d(TAG, "In onCreate() event");
        contactListView = getListView();
        contactListView.setOnItemClickListener(viewContactListener);

        //map each contact's name to a TV in the ListView layout
        String[] from = {"name"};
        int[] to = new int[] {R.id.contactTextView};
        CursorAdapter contactAdapter = new SimpleCursorAdapter(AddressBook.this,
                R.layout.contact_list_item, null, from, to);    
        setListAdapter(contactAdapter);  //set contactView's adapter
    }

    @Override
    protected void onResume(){

        Log.d(TAG, "In onResume() event");
        super.onResume();  //call super's onResume method

        //create a new GetContactsTask and execute it
        new GetContactsTask().execute((Object[]) null);
    }  //end onResume

    @Override
    protected void onStop(){

        Log.d(TAG, "In onStop() event");
        Cursor cursor = contactAdapter.getCursor();  //get current Cursor
        if (cursor != null)
            cursor.deactivate();  //deactivate it

        contactAdapter.changeCursor(null);  //adapter now has no Cursor
        super.onStop();
    }  //end onStop

    //performs database query outside GUI thread
    private class GetContactsTask extends AsyncTask<Object, Object, Cursor>{        

        DatabaseConnector DBC = new DatabaseConnector(AddressBook.this);

        //perform the database access
        @Override
        protected Cursor doInBackground(Object... params){
            DBC.open();

            //get a cursor containing call contacts
            return DBC.getAllContacts();
        }  //end method doInBackground

        //use the Cursor returned from the doInBackground method
        @Override
        protected void onPostExecute(Cursor result){
            Log.d(TAG, "In onPostExecute() event");
            contactAdapter.changeCursor(result);  //set the adapter's Cursor
            DBC.close();
        }  //end method onPostExecute
    }  //end class GetContactsTask

    //create the Activity's menu from a menu resource XML file  
    public boolean onCreateOptionsMenu(Menu menu) {

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

    //handle the choice from options menu
    @Override
    public boolean onOptionsItemSelected(MenuItem item){

        //create a new Intent to launch the AddEditContact Activity
        Intent addNewContact = new Intent(AddressBook.this, AddEditContact.class);
        startActivity(addNewContact);  //start the AddEditContact Activity
        return super.onOptionsItemSelected(item);  //call super's method
    }  //end onOptionsItemSelected

    //event listener that responds to the users touching a contact's name in the ListView
    OnItemClickListener viewContactListener = new OnItemClickListener(){

        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3){

            //create an Intent to launch the ViewContact Activity
            Intent viewContact = new Intent(AddressBook.this, ViewContact.class);

            //pass the selected contact's row ID as an extra with the intent
            viewContact.putExtra(ROW_ID, arg3);
            startActivity(viewContact);  //start the ViewContact Activity           
        }  //end method onItemClick
    };  //end viewContactListener
}  //end class AddressBook

问题似乎是我的“getContactsTask”内部类中的这一行:contactAdapter.changeCursor(result); 一旦我点击这条线,我就会得到一个空指针异常。作为参考,这里是我在 getContactsTask 中引用的数据库连接器类:

//DatabaseConnector.java
//Provides easy connection and creation of UserContacts database.
package com.deitel.addressbook;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.util.Log;

public class DatabaseConnector {

    public static final String TAG ="AddressBookBot";

    //database name
    private static final String DATABASE_NAME = "UserContacts";
    private SQLiteDatabase database;  //database object
    private DatabaseOpenHelper DBOpenHelper;  //database helper

    //public constructor for DatabaseConnector
    public DatabaseConnector(Context context){

        //create a new DatabaseOpenHelper
        DBOpenHelper = new DatabaseOpenHelper(context, DATABASE_NAME, null, 1);
    }  //end constructor

    //open the database connection
    public void open() throws SQLException{

        //create or open a database for reading/writing
        database = DBOpenHelper.getWritableDatabase();
    }  //end method open

    //close the database connection
    public void close(){

        if(database != null)
            database.close();  //close database connection
    }  //end method close

    //inserts a new contact in the database
    public void insertContact(String name, String email, String phone, String state, String city){

        ContentValues newContact = new ContentValues();
        newContact.put("name", name);
        newContact.put("email", email);
        newContact.put("phone", phone);
        newContact.put("street", state);
        newContact.put("city", city);

        open();  //open the database
        database.insert("contacts", null, newContact);
        close();  //close the database
    }  //end insertContact

    //inserts a new contact in the database
    public void updateContact(long id, String name, String email, String phone, String state, String city){

        ContentValues editContact = new ContentValues();
        editContact.put("name", name);
        editContact.put("email", email);
        editContact.put("phone", phone);
        editContact.put("street", state);
        editContact.put("city", city);

        open();  //open the database
        database.update("contacts", editContact, "_id=" + id, null);
        close();  //close the database
    }  //end updateContact

    //return a Cursor with all contact information in the database
    public Cursor getAllContacts(){
        Log.d(TAG, "in getAllContacts");
        return database.query("contacts", new String[] {"_id", "name"}, null, null, null, null, "name");

    }  //end getAllContacts

    //get a Cursor containing all information about the contact specified by the given id
    public Cursor getOneContact(long id){

        return database.query("contacts", null, "_id='" + id, null, null, null, null);
    }  //end getOneContact

    //delete the contact specified by the given String name
    public void deleteContact(long id){

        open();  //open the database
        database.delete("contacts", "_id=" + id, null);
        close();  //close the database
    }  //end deleteContact

    private class DatabaseOpenHelper extends SQLiteOpenHelper{

        //public constructor
        public DatabaseOpenHelper(Context context, String name, CursorFactory factory, int version){
            super(context, name, factory, version);
        }  //end DatabaseOpenHelper contstructor

        //creates the contacts table when the database is created
        @Override
        public void onCreate(SQLiteDatabase db){

            //query to create a new table named contacts
            String createQuery = "CREATE TABLE contacts" + "(_id integer primary key autoincrement," + "name TEXT, email TEXT, phone TEXT," + "street TEXT, city TEXT);";

            db.execSQL(createQuery);  //execute the query
        }  //end method onCreate

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){

        }  //end onUpgrade
    }  //end class DatabaseOpenHelper   
}  //end class DataBaseConnector

对此的任何帮助或澄清将不胜感激!

4

3 回答 3

1

我认为您的 Cursor 对象引用了 null 。结果参考变量指向哪个查询?

于 2013-08-25T22:00:32.400 回答
0

在 getAllContacts() 中进行查询之前,您没有打开数据库。该函数应如下所示:

public Cursor getAllContacts() {
    Log.d(TAG, "in getAllContacts");

    Cursor cursor = null;

    open();   // open the database
    cursor = database.query("contacts", new String[] {"_id", "name"}, 
                         null, null, null, null, "name");
    close(); // close the database

    return cursor;
}

函数 getOneContact() 也存在类似问题。

于 2013-08-26T03:09:36.420 回答
0

这是我做错的:

我声明一个

private CursorAdapter contactAdapter;

在 AddressBook.java 文件中。然后稍后而不是放

contactAdapter = new SimpleCursorAdapter(AddressBook.this,
                R.layout.contact_list_item, null, from, to);

我当场再次声明

CursorAdapter contactAdapter = new SimpleCursorAdapter(AddressBook.this,
                R.layout.contact_list_item, null, from, to); 

这会导致空指针异常。清理第二次声明错误后,应用程序运行良好。再次感谢所有帮助过的人:)

于 2013-08-27T00:20:30.643 回答