首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >安卓应用在启动时崩溃: ContactsFragment中的SQLite NullPointerException

安卓应用在启动时崩溃: ContactsFragment中的SQLite NullPointerException
EN

Stack Overflow用户
提问于 2015-05-06 06:07:52
回答 2查看 24.3K关注 0票数 10

我正在努力集成一个数据库,以保存和存储基本联系信息,以便在以后检索。然而,我的应用程序现在在启动时崩溃,所以我甚至不能验证表是否正在创建等。

代码语言:javascript
复制
05-05 16:39:50.671  11631-11631/treehouse.greenlight E/AndroidRuntime﹕   FATAL EXCEPTION: main
Process: treehouse.greenlight, PID: 11631
java.lang.RuntimeException: Unable to start activity ComponentInfo{treehouse.greenlight/treehouse.greenlight.Home_screen}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2205)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2255)
        at android.app.ActivityThread.access$800(ActivityThread.java:142)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1203)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5118)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:610)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
        at treehouse.greenlight.MyDBHandler.addContact(MyDBHandler.java:54)
        at treehouse.greenlight.ContactsFragment.onCreateLoader(ContactsFragment.java:117)
        at android.support.v4.app.LoaderManagerImpl.createLoader(LoaderManager.java:490)
        at android.support.v4.app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.java:499)
        at android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:553)
        at treehouse.greenlight.ContactsFragment.onActivityCreated(ContactsFragment.java:71)
        at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1797)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:979)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1120)
        at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1929)
        at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:547)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
        at android.app.Activity.performStart(Activity.java:5285)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2178) 

数据库处理程序代码:

代码语言:javascript
复制
public class MyDBHandler extends SQLiteOpenHelper {

private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "contactsDB.db";
public static final String TABLE_CONTACTS = "contacts";
private Context context;
public static final String COLUMN_ID = "_id";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_PHONE = "phone";
public static final String COLUMN_STATUS = "status";
public static final String COLUMN_BLURB = "blurb";

public MyDBHandler(Context context, String name,
                   CursorFactory factory, int version)  {
    super(context, DATABASE_NAME, factory, DATABASE_VERSION);

}
    @Override
    public void onCreate (SQLiteDatabase db){

        String CREATE_CONTACTS_TABLE = "CREATE TABLE " +
                TABLE_CONTACTS + "("
                + COLUMN_ID + " INTEGER PRIMARY KEY," + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
                + " TEXT," + ContactsContract.CommonDataKinds.Phone.NUMBER + " INTEGER,"
                + COLUMN_STATUS + " TEXT," + COLUMN_BLURB
                + " TEXT" + ");";
        db.execSQL(CREATE_CONTACTS_TABLE);
    }

    @Override
    public void onUpgrade (SQLiteDatabase db,int oldVersion, int newVersion){
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS);
        onCreate(db);
    }
public void addContact(ContactsDb contacts) {

    ContentValues values = new ContentValues();
    values.put(COLUMN_NAME, contacts.getName());
    values.put(COLUMN_PHONE, contacts.getPhone());
    values.put(COLUMN_STATUS, contacts.getStatus());
    values.put(COLUMN_BLURB, contacts.getBlurb());

    SQLiteDatabase db = this.getWritableDatabase();
    db.insert(TABLE_CONTACTS, null, values);

}

logcat说问题出在SQLiteDatabase db = this.getWriteableDatabase();

这也是我令人不快的Contactsfragment:

代码语言:javascript
复制
public class ContactsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {

private CursorAdapter mAdapter;
private Context context;
TextView idView;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // create adapter once
    Context context = getActivity();
    int layout = R.layout.activity_list_item_1;
    Cursor c = null; // there is no cursor yet
    int flags = 0; // no auto-requery! Loader requeries.
    mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags);

}


public void ContactsDb(Context context) {
    this.context=context;


}
Uri contentUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;

String[] PROJECTION = {
        ContactsContract.Contacts.HAS_PHONE_NUMBER,
        ContactsContract.Contacts._ID, // _ID is always required
        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY, // that is what we want to display
        Contacts.TIMES_CONTACTED,
        ContactsContract.CommonDataKinds.Phone.NUMBER

};

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    // each time we are started use our listadapter
    setListAdapter(mAdapter);
    // and tell loader manager to start loading
    getLoaderManager().initLoader(0, null, this);
}

// columns requested from the database


// and name should be displayed in the text1 textview in item layout

public String[] has_phone = {ContactsContract.Contacts.HAS_PHONE_NUMBER};

    String phone = "0";
    int dbPhone = 0;
private  final String[] FROM = {Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.CommonDataKinds.Phone.NUMBER};
private final int[] TO = {android.R.id.text1, dbPhone};


public void newContact (View view) {
    MyDBHandler dbHandler = new MyDBHandler(context, null, null, 1);

    String name = Contacts.DISPLAY_NAME_PRIMARY;
    int dbPhone =
    Integer.parseInt(phone);

    String status ="";
    String blurb ="";
    ContactsDb contacts =
            new ContactsDb(name, dbPhone, status, blurb);
    dbHandler.addContact(contacts);

}


@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    Context context = this.context;
    // load from the "Contacts table"
    MyDBHandler dbHandler = new MyDBHandler(context, null, null, 1);

    String name = Contacts.DISPLAY_NAME_PRIMARY;
    int phone = Integer.parseInt(ContactsContract.CommonDataKinds.Phone.NUMBER);

    String status ="Busy";
    String blurb ="N/A";

    ContactsDb contacts =
            new ContactsDb(name, dbPhone, status, blurb);
    dbHandler.addContact(contacts);

    // no sub-selection, no sort order, simply every row
    // projection says we want just the _id and the name column
    return new CursorLoader(getActivity(),
            contentUri,
            PROJECTION,
            ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? AND " + Contacts.TIMES_CONTACTED + ">=?", // This is selection string, we're looking for records that HAS_PHONE_NUMBER is 1
            new String[]{"1", "0"}, // 1 means that contact has a phone number & 60 is the amount of times contacted (arbitrary - needs to be fixed before release)
            null);
}

最后,这里是ContactsDB类:

代码语言:javascript
复制
public ContactsDb(String name, int phone, String status, String blurb) {

    this._name = name;
    this._phone = phone;
    this._status = status;
    this._blurb = blurb;

任何帮助都是非常感谢的--我认为问题出在我的上下文为null。我只是不确定为什么它会像我在MyDBHandler文件中定义的那样。到目前为止,我无法验证数据库是否正在创建,更不用说保存数据了。

干杯&谢谢你的时间和耐心,Shyam

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-06 06:33:06

看起来您意外地创建了一个context局部变量,而没有使用实例变量。

因此,当您将context传递给MyDBHandler时,它是空的,所以当您调用this.getWritableDatabase()时,this也是空的。因此,您将获得NullPointerException,如您在日志中所看到的:

代码语言:javascript
复制
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)

尝试将所有与Context相关的代码移动到onActivityCreated(),以确保拥有有效的Context,并确保使用实例变量而不是局部变量:

代码语言:javascript
复制
public class ContactsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {

private CursorAdapter mAdapter;
private Context context; //this is the Context you will use
TextView idView;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // create adapter once
    //Context context = getActivity(); //Here was the problem
    //int layout = R.layout.activity_list_item_1;
    //Cursor c = null; // there is no cursor yet
    //int flags = 0; // no auto-requery! Loader requeries.
    //mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags);

}


public void ContactsDb(Context context) {
    this.context=context;


}
Uri contentUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;

String[] PROJECTION = {
        ContactsContract.Contacts.HAS_PHONE_NUMBER,
        ContactsContract.Contacts._ID, // _ID is always required
        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY, // that is what we want to display
        Contacts.TIMES_CONTACTED,
        ContactsContract.CommonDataKinds.Phone.NUMBER

};

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    //Add this here:
    context = getActivity(); //use the instance variable
    int layout = R.layout.activity_list_item_1;
    Cursor c = null; // there is no cursor yet
    int flags = 0; // no auto-requery! Loader requeries.
    mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags);

    // each time we are started use our listadapter
    setListAdapter(mAdapter);
    // and tell loader manager to start loading
    getLoaderManager().initLoader(0, null, this);
}

// columns requested from the database


// and name should be displayed in the text1 textview in item layout

public String[] has_phone = {ContactsContract.Contacts.HAS_PHONE_NUMBER};

    String phone = "0";
    int dbPhone = 0;
private  final String[] FROM = {Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.CommonDataKinds.Phone.NUMBER};
private final int[] TO = {android.R.id.text1, dbPhone};


public void newContact (View view) {

    //context should now be valid:
    MyDBHandler dbHandler = new MyDBHandler(context, null, null, 1);

    String name = Contacts.DISPLAY_NAME_PRIMARY;
    int dbPhone =
    Integer.parseInt(phone);

    String status ="";
    String blurb ="";
    ContactsDb contacts =
            new ContactsDb(name, dbPhone, status, blurb);
    dbHandler.addContact(contacts);

}
//........
票数 18
EN

Stack Overflow用户

发布于 2018-07-30 06:22:50

在适配器中从onCreateViewHolder方法中的db类生成对象以解决此错误

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30064080

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档