启动时Android应用程序崩溃:ContactsFragment中的SQLite NullPointerException

前端之家收集整理的这篇文章主要介绍了启动时Android应用程序崩溃:ContactsFragment中的SQLite NullPointerException前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在集成数据库来保存和存储以后要检索的基本联系信息.但是,我的应用程序现在在启动时崩溃,所以我甚至无法验证是否正在创建表等.
  1. 05-05 16:39:50.671 11631-11631/treehouse.greenlight E/AndroidRuntime FATAL EXCEPTION: main
  2. Process: treehouse.greenlight,PID: 11631
  3. 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
  4. at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2205)
  5. at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2255)
  6. at android.app.ActivityThread.access$800(ActivityThread.java:142)
  7. at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1203)
  8. at android.os.Handler.dispatchMessage(Handler.java:102)
  9. at android.os.Looper.loop(Looper.java:136)
  10. at android.app.ActivityThread.main(ActivityThread.java:5118)
  11. at java.lang.reflect.Method.invoke(Native Method)
  12. at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
  13. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:610)
  14. Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.sqliteDatabase android.content.Context.openOrCreateDatabase(java.lang.String,android.database.DatabaseErrorHandler)' on a null object reference
  15. at android.database.sqlite.sqliteOpenHelper.getDatabaseLocked(sqliteOpenHelper.java:224)
  16. at android.database.sqlite.sqliteOpenHelper.getWritableDatabase(sqliteOpenHelper.java:164)
  17. at treehouse.greenlight.MyDBHandler.addContact(MyDBHandler.java:54)
  18. at treehouse.greenlight.ContactsFragment.onCreateLoader(ContactsFragment.java:117)
  19. at android.support.v4.app.LoaderManagerImpl.createLoader(LoaderManager.java:490)
  20. at android.support.v4.app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.java:499)
  21. at android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:553)
  22. at treehouse.greenlight.ContactsFragment.onActivityCreated(ContactsFragment.java:71)
  23. at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1797)
  24. at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:979)
  25. at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
  26. at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1120)
  27. at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1929)
  28. at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:547)
  29. at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
  30. at android.app.Activity.performStart(Activity.java:5285)
  31. at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2178)

数据库处理程序代码

  1. public class MyDBHandler extends sqliteOpenHelper {
  2.  
  3. private static final int DATABASE_VERSION = 1;
  4. private static final String DATABASE_NAME = "contactsDB.db";
  5. public static final String TABLE_CONTACTS = "contacts";
  6. private Context context;
  7. public static final String COLUMN_ID = "_id";
  8. public static final String COLUMN_NAME = "name";
  9. public static final String COLUMN_PHONE = "phone";
  10. public static final String COLUMN_STATUS = "status";
  11. public static final String COLUMN_BLURB = "blurb";
  12.  
  13. public MyDBHandler(Context context,String name,CursorFactory factory,int version) {
  14. super(context,DATABASE_NAME,factory,DATABASE_VERSION);
  15.  
  16. }
  17. @Override
  18. public void onCreate (sqliteDatabase db){
  19.  
  20. String CREATE_CONTACTS_TABLE = "CREATE TABLE " +
  21. TABLE_CONTACTS + "("
  22. + COLUMN_ID + " INTEGER PRIMARY KEY," + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
  23. + " TEXT," + ContactsContract.CommonDataKinds.Phone.NUMBER + " INTEGER,"
  24. + COLUMN_STATUS + " TEXT," + COLUMN_BLURB
  25. + " TEXT" + ");";
  26. db.execsql(CREATE_CONTACTS_TABLE);
  27. }
  28.  
  29. @Override
  30. public void onUpgrade (sqliteDatabase db,int oldVersion,int newVersion){
  31. db.execsql("DROP TABLE IF EXISTS " + TABLE_CONTACTS);
  32. onCreate(db);
  33. }
  34. public void addContact(ContactsDb contacts) {
  35.  
  36. ContentValues values = new ContentValues();
  37. values.put(COLUMN_NAME,contacts.getName());
  38. values.put(COLUMN_PHONE,contacts.getPhone());
  39. values.put(COLUMN_STATUS,contacts.getStatus());
  40. values.put(COLUMN_BLURB,contacts.getBlurb());
  41.  
  42. sqliteDatabase db = this.getWritableDatabase();
  43. db.insert(TABLE_CONTACTS,null,values);
  44.  
  45. }

logcat说问题是sqliteDatabase db = this.getWriteableDatabase();

这也是我违规的Contactsfragment:

  1. public class ContactsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {
  2.  
  3. private CursorAdapter mAdapter;
  4. private Context context;
  5. TextView idView;
  6. @Override
  7. public void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9.  
  10. // create adapter once
  11. Context context = getActivity();
  12. int layout = R.layout.activity_list_item_1;
  13. Cursor c = null; // there is no cursor yet
  14. int flags = 0; // no auto-requery! Loader requeries.
  15. mAdapter = new SimpleCursorAdapter(context,layout,c,FROM,TO,flags);
  16.  
  17. }
  18.  
  19.  
  20. public void ContactsDb(Context context) {
  21. this.context=context;
  22.  
  23.  
  24. }
  25. Uri contentUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
  26.  
  27. String[] PROJECTION = {
  28. ContactsContract.Contacts.HAS_PHONE_NUMBER,ContactsContract.Contacts._ID,// _ID is always required
  29. ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY,// that is what we want to display
  30. Contacts.TIMES_CONTACTED,ContactsContract.CommonDataKinds.Phone.NUMBER
  31.  
  32. };
  33.  
  34. @Override
  35. public void onActivityCreated(Bundle savedInstanceState) {
  36. super.onActivityCreated(savedInstanceState);
  37.  
  38. // each time we are started use our listadapter
  39. setListAdapter(mAdapter);
  40. // and tell loader manager to start loading
  41. getLoaderManager().initLoader(0,this);
  42. }
  43.  
  44. // columns requested from the database
  45.  
  46.  
  47. // and name should be displayed in the text1 textview in item layout
  48.  
  49. public String[] has_phone = {ContactsContract.Contacts.HAS_PHONE_NUMBER};
  50.  
  51. String phone = "0";
  52. int dbPhone = 0;
  53. private final String[] FROM = {Contacts.DISPLAY_NAME_PRIMARY,ContactsContract.CommonDataKinds.Phone.NUMBER};
  54. private final int[] TO = {android.R.id.text1,dbPhone};
  55.  
  56.  
  57. public void newContact (View view) {
  58. MyDBHandler dbHandler = new MyDBHandler(context,1);
  59.  
  60. String name = Contacts.DISPLAY_NAME_PRIMARY;
  61. int dbPhone =
  62. Integer.parseInt(phone);
  63.  
  64. String status ="";
  65. String blurb ="";
  66. ContactsDb contacts =
  67. new ContactsDb(name,dbPhone,status,blurb);
  68. dbHandler.addContact(contacts);
  69.  
  70. }
  71.  
  72.  
  73. @Override
  74. public Loader<Cursor> onCreateLoader(int id,Bundle args) {
  75. Context context = this.context;
  76. // load from the "Contacts table"
  77. MyDBHandler dbHandler = new MyDBHandler(context,1);
  78.  
  79. String name = Contacts.DISPLAY_NAME_PRIMARY;
  80. int phone = Integer.parseInt(ContactsContract.CommonDataKinds.Phone.NUMBER);
  81.  
  82. String status ="Busy";
  83. String blurb ="N/A";
  84.  
  85. ContactsDb contacts =
  86. new ContactsDb(name,blurb);
  87. dbHandler.addContact(contacts);
  88.  
  89. // no sub-selection,no sort order,simply every row
  90. // projection says we want just the _id and the name column
  91. 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
  92. 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)
  93. null);
  94. }

最后,这是ContactsDB类:

  1. public ContactsDb(String name,int phone,String status,String blurb) {
  2.  
  3. this._name = name;
  4. this._phone = phone;
  5. this._status = status;
  6. this._blurb = blurb;

非常感谢任何帮助 – 我认为问题在于我的Context为null.我只是不确定为什么它会在我的MyDBHandler文件中定义它.截至目前,我无法验证是否正在创建数据库,更不用说保存数据了.

干杯&感谢您的时间和耐心,
希亚姆

解决方法

看起来你不小心创建了一个上下文局部变量而不是使用实例变量.

因此,当您将其传递给MyDBHandler时,context为null,因此当您调用this.getWritableDatabase()时,它为null.因此,您可以在日志中看到NullPointerException:

  1. Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.sqliteDatabase android.content.Context.openOrCreateDatabase(java.lang.String,android.database.DatabaseErrorHandler)' on a null object reference
  2. at android.database.sqlite.sqliteOpenHelper.getDatabaseLocked(sqliteOpenHelper.java:224)
  3. at android.database.sqlite.sqliteOpenHelper.getWritableDatabase(sqliteOpenHelper.java:164)

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

  1. public class ContactsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {
  2.  
  3. private CursorAdapter mAdapter;
  4. private Context context; //this is the Context you will use
  5. TextView idView;
  6. @Override
  7. public void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9.  
  10. // create adapter once
  11. //Context context = getActivity(); //Here was the problem
  12. //int layout = R.layout.activity_list_item_1;
  13. //Cursor c = null; // there is no cursor yet
  14. //int flags = 0; // no auto-requery! Loader requeries.
  15. //mAdapter = new SimpleCursorAdapter(context,ContactsContract.CommonDataKinds.Phone.NUMBER
  16.  
  17. };
  18.  
  19. @Override
  20. public void onActivityCreated(Bundle savedInstanceState) {
  21. super.onActivityCreated(savedInstanceState);
  22.  
  23. //Add this here:
  24. context = getActivity(); //use the instance variable
  25. int layout = R.layout.activity_list_item_1;
  26. Cursor c = null; // there is no cursor yet
  27. int flags = 0; // no auto-requery! Loader requeries.
  28. mAdapter = new SimpleCursorAdapter(context,flags);
  29.  
  30. // each time we are started use our listadapter
  31. setListAdapter(mAdapter);
  32. // and tell loader manager to start loading
  33. getLoaderManager().initLoader(0,dbPhone};
  34.  
  35.  
  36. public void newContact (View view) {
  37.  
  38. //context should now be valid:
  39. MyDBHandler dbHandler = new MyDBHandler(context,blurb);
  40. dbHandler.addContact(contacts);
  41.  
  42. }
  43. //........

猜你在找的Android相关文章