2011-02-14 69 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就成爲一個全局實例,您可以從每個活動中獲得該實例。