在DataBaseHelper类中实现Parcelable

时间:2011-02-14 15:01:42

标签: java android sqlite

我一直致力于将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;
        }

    };

}

任何帮助非常感谢。 提前谢谢。

2 个答案:

答案 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就成为了一个可以从每个活动中获得的全局实例。