我一直在研究一种方法,以将“活动”之间的引用传递给我的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;
}
};
}
任何帮助,不胜感激。
提前致谢。
最佳答案
您似乎不必要地使事情复杂化。你说:
我不想重新创建新实例
每个新数据库中的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...
//...
}
我认为这不值得付出努力,但这取决于您自己决定。
关于java - 在DataBaseHelper类中实现Parcelable,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4993667/