我无法理解如何初始化数据库错误:
java.lang.NullPointerException
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:188)
at com.example.stopcall.app.dal.PhoneDal.getItem(PhoneDal.java:105)
at com.example.stopcall.app.ItemDetailFragment$1.onClick(ItemDetailFragment.java:87)
at android.view.View.performClick(View.java:4654)
at android.view.View$PerformClick.run(View.java:19438)
at android.os.Handler.handleCallback(Handler.java:733)
代码落在这一行:SQLiteDatabase db = this.getWritableDatabase();
来自此代码:
public class PhoneDal extends SQLiteOpenHelper {
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = Constants.DB_NAME;
private static final String BLOCKED_PHONES_TABLE = "BLOCKED_PHONES_TABLE";
private static final String COMMENTS_TABLE = "COMMENTS_TABLE";
public PhoneDal(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// SQL statement to create book table
String CREATE_BLOCKED_PHONES_TABLE = "CREATE TABLE "
+ BLOCKED_PHONES_TABLE + " ( "
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "phone TEXT, "
+ "isBlocked BIT )";
db.execSQL(CREATE_BLOCKED_PHONES_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion > oldVersion) {
Log.w("MyAppTag", "Updating database from version " + oldVersion
+ " to " + newVersion + " .Existing data will be lost.");
// Drop older books table if existed
db.execSQL("DROP TABLE IF EXISTS " + BLOCKED_PHONES_TABLE);
// create fresh books table
this.onCreate(db);
}
}
private static final String KEY_ID = "id";
private static final String KEY_PHONE = "KEY_PHONE";
private static final String KEY_IS_BLOCKED = "KEY_IS_BLOCKED";
public void addItem(Phone phone) {
// 1. get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
初始化代码:
public class ItemDetailFragment extends Fragment {
/**
* The fragment argument representing the item ID that this fragment
* represents.
*/
public static final String ARG_ITEM_ID = "item_id";
/**
* The dummy content this fragment is presenting.
*/
private DummyContent.DummyItem mItem;
private PhoneDal phoneDal;
private CommentDal commentDal;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public ItemDetailFragment() {
this.mItem = mItem;
this.phoneDal = new PhoneDal(getActivity());
this.commentDal = new CommentDal(getActivity());
}
@SuppressLint("ValidFragment")
public ItemDetailFragment(DummyContent.DummyItem mItem, PhoneDal phoneDal, CommentDal commentDal) {
this.mItem = mItem;
this.phoneDal = phoneDal;
this.commentDal = commentDal;
}
答案 0 :(得分:3)
public ItemDetailFragment() { this.phoneDal = new PhoneDal(getActivity());
片段构造函数太早,无法调用getActivity()
- 它将返回null。在Context
构造函数中将null作为SQLiteOpenHelper
传递会在调用get...Database()
时导致异常。
将您的PhoneDal
初始化推迟到片段生命周期中的onAttach()
或更高版本。
答案 1 :(得分:0)
您正在使用null作为上下文初始化PhoneDal,这会在以后导致NPE。问题是你在Fragment的构造函数中调用getActivity()
,此时它将返回null。
不要为View和Fragment等组件实现构造函数!
相反,使用像onCreate,OnStart,OnAttach这样的专用方法来初始化和操作它们。
在Fragment的构造函数的Javadoc中也提到了这一点:
应用程序通常不应该实现构造函数。首先 将应用程序代码放置在可以使用片段的运行中 在onAttach(Activity)中,片段实际上就是这个点 与其活动有关。
有关Fragment生命周期的更多信息:Fragments
顺便提一下,建议使用应用程序上下文初始化SQLiteOpenHelper:Avoid memory leaks