2011-02-14 45 views
0

我一直在努力将活动之间的引用传递给我的DataBaseHelper类。我不想在每个新活动中重新创建DataBaseHelper的新实例。 从我看到的,最好的方法是实现android.os.parcelable,这很好。 然而,当我尝试重写DataBaseHelper构造:在DataBaseHelper类中实现Parcelable

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

你似乎不必要地使事情复杂化。你说:

我不想重新创建新实例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... 
      //... 
} 

我不认为这很可能是值得的,但是这是由你来决定。

+0

啊对,我明显误解了Parcelable的目的。我认为它只是传递现有DataBaseHelper的一个实例(关注资源)。这是一个更难的方法,我将创建一个新的DataBaseHelper,感谢您的快速回复。 – Mal 2011-02-14 15:15:06

0

实现此目的的一种方法是拥有一个扩展Application的类。然后,在那个类中创建DBHelper并提供一个getter。 然后,在其他活动中,您可以这样做:

DBHelper myHelper = getApplication()。getDBHelper();

这样DBHelper就成为一个全局实例,您可以从每个活动中获得该实例。