我一直致力于将Activities之间的引用传递给我的DataBaseHelper类。我不想在每个新活动中重新创建DataBaseHelper的新实例。 从我所看到的,最好的方法是实现android.os.parcelable,这很好。 但是,当我尝试使用:
覆盖DataBaseHelper构造函数时public DataBaseHelper(Parcel source)
我收到错误,告诉我构造函数未定义。 我有点理解这意味着什么,但我不确定如何解决这个问题,因此在这个类中实现Parcelable。 下面是DatabaseHelper类,可分区代码位于底部。
package com.drager;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
public class DataBaseHelper extends SQLiteOpenHelper implements Parcelable{
//private static String DB_PATH = "/data/data/com.drager/databases/";
private static String DB_PATH = Environment.getDataDirectory()+"/data/com.drager/databases/";
final static String DB_NAME = "myDBName";
private SQLiteDatabase myDataBase=null;
private final Context myContext;
private DataBaseHelper myDbHelper;
private static String TAG ="MyActivity";
public DataBaseHelper(Context context){
super(context, DB_NAME, null, 1);
this.myContext = context;
}
public DataBaseHelper(Parcel source) {
super(source);
// TODO Auto-generated constructor stub
}
public DataBaseHelper createDataBase() throws IOException{
boolean dbExist =checkDataBase();
//SQLiteDatabase db_read =null;
Log.i(TAG,"############value of dbExist"+dbExist+"##########");
if (dbExist){
copyDataBase();
//db must exist
}
else{
myDbHelper = new DataBaseHelper(myContext);
myDataBase = myDbHelper.getReadableDatabase();
myDataBase.close();
//this.getReadableDatabase();
//db_read.close();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("error copying database");
}
}
return this;
}
public Cursor executeStatement(){
Log.i(TAG,"in execute statement");
Cursor cursor=null;
cursor=myDataBase.rawQuery("SELECT _ID, title, value "+
"FROM constants ORDER BY title",
null);
return cursor;
}
public String[] getTextViewItem(){
Cursor cursor=null;
String str="";
String[] resultsString;
//store query results in cursor
cursor=myDataBase.rawQuery("SELECT shrt_description FROM description",
null);
ArrayList strings = new ArrayList();
for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){
str =cursor.getString(cursor.getColumnIndex("shrt_description"));
strings.add(str);
}
resultsString =(String[])strings.toArray(new String[strings.size()]);
close();//close database after use
return resultsString;
}
public String[] getDetailedDescription(){
Cursor cursor=null;
String str="";
String[] resultsString;
//store query results in cursor
cursor=myDataBase.rawQuery("SELECT detailed_description FROM description",
null);
ArrayList strings = new ArrayList();
for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){
str =cursor.getString(cursor.getColumnIndex("detailed_description"));
strings.add(str);
}
resultsString =(String[])strings.toArray(new String[strings.size()]);
close();//close database after use
return resultsString;
}
public void copyDataBase() throws IOException{
// open db as input stream
InputStream myInput;
//open empty db as output stream
OutputStream myOutPut;
try {
myInput = myContext.getAssets().open(DB_NAME);
//path to newly created db
String outFileName =DB_PATH + DB_NAME;
myOutPut = new FileOutputStream(outFileName);
//transfer bytes from the inputFile to the outPutFile
byte[] buffer = new byte[1024];
int length;
while((length = myInput.read(buffer))>0){
myOutPut.write(buffer, 0, length);
}
myOutPut.flush();
myOutPut.close();
myInput.close();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
String myPath = DB_PATH + DB_NAME;
try {
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLException e) {
e.printStackTrace();
return false;
}
if (checkDB != null){
checkDB.close();
}
return true;
//return checkDB !=null ? true : false;
}
public void openDataBase()throws SQLException{
//open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
@Override
public synchronized void close(){
if(myDataBase != null){
myDataBase.close();
}
super.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeParcelable((Parcelable) myDataBase, 0);
dest.writeString(DB_PATH);
dest.writeString(DB_NAME);
dest.writeString(TAG);
dest.writeParcelable((Parcelable) myContext, 0);
dest.writeParcelable(myDbHelper, 0);
}
public static final Parcelable.Creator<DataBaseHelper> CREATOR = new Parcelable.Creator<DataBaseHelper>() {
@Override
public DataBaseHelper createFromParcel(Parcel source) {
// TODO Auto-generated method stub
return new DataBaseHelper(source);
}
@Override
public DataBaseHelper[] newArray(int size) {
// TODO Auto-generated method stub
return null;
}
};
}
任何帮助非常感谢。 提前谢谢。
答案 0 :(得分:2)
你似乎不必要地使事情复杂化。你说:
我不想重新创建新实例 每个新的DataBaseHelper 活动。从我所看到的, 最好的方法是实现 android.os.parcelable,这很好。
但是从包恢复DataBaseHelper对象会创建DataBaseHelper类的新实例;这比创建一个新的DataBaseHelper更难。
在任何情况下,虽然您没有在此处复制并粘贴错误消息,但我想我知道您收到了什么错误:并不是您的DataBaseHelper
类不包含正确的构造函数;它确实。这是超类SQLiteOpenHelper
没有实现Parcelable
。解决这个问题的唯一方法就是自己管理所有SQLiteOpenHelper
的状态。也就是说,将SQLiteOpenHelper的状态包含在writeToParcel
实现的一部分中,并将该状态恢复为DatabaseHelper(Parcel)
的一部分。然后构造函数将调用SQLiteOpenHelper
的默认构造函数。结果构造函数看起来像这样:
public DataBaseHelper(Parcel source, Context context, String name,
SQLiteDatabase.CursorFactory factory, int version) {
// NOTE: You've got to pass in an appropriate Context; I'm sure it would not work
// to try to include the original Activity in the Parcel! That means that your
// constructor **must** include the Context as one of its arguments. Conceivably,
// the name, factory, and version could be taken from the Parcel rather than being
// passed in the constructor arguments. Again, I ask: Is it worth the hassle?
super(context, name, factory, version);
// First, restore any relevant `SQLiteOpenHelper` state...
//...
// Now restore any relevant DataBaseHelper state...
//...
}
我认为这不值得付出努力,但这取决于你决定。
答案 1 :(得分:0)
实现此目的的一种方法是拥有一个扩展Application的类。然后,在该类中创建DBHelper并提供getter。 然后,在您的其他活动中,您可以执行以下操作:
DBHelper myHelper = getApplication()。getDBHelper();
这样,DBHelper就成为了一个可以从每个活动中获得的全局实例。