2015-10-07 80 views
-1

我想學習一些與碎片的Android開發,但遇到了問題。Android的片段數據庫

我的應用程序需要多個表,因此我採用了創建主DB適配器的方法來創建所有表,併爲每個表命令使用單獨的適配器。

我遇到的問題是在recipe_Fragment中實例化recipe_Adapter以訪問適配器中的命令。
有什麼我需要改變,使上下文片段友好?

我認爲所有適配器都是分開的,對嗎?
在一個大的主DB適配器中爲每個表提供所有命令會更好嗎?

當我根據Android Studio的指示更改參數以適應片段時,出現以下錯誤信息;該錯誤表示找到了錯誤的第一個參數(即'上下文')。
我試圖將其更改爲片段,但這給了我更多的錯誤。

更新解決! 我將下面的片段類更改爲工作版本。我試圖在創建片段之前訪問數據庫,所以我試圖傳遞那些沒有的東西。新代碼在try和catch語句中的onActivityCreated()中訪問數據庫。

主數據庫適配器 package app.rory.pocket_chef.Adapters;

import android.content.Context; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 

import java.sql.SQLException; 

/** 
* Created by Rory on 06/10/15. 
*/ 
public class DBAdapter { 

    public static final String DATABASE_NAME = "pocket_chef"; 

    public static final int DATABASE_VERSION = 1; 

    //creating each table 
    private static final String CREATE_TABLE_RECIPES = "create table if not exists recipes(" + 
      "_id INT PRIMARY KEY AUTOINCREMENT, " + 
      "name VARCHAR" + 
      "ingredents TEXT" + 
      "instructions TEXT" + 
      "description TEXT" + 
      "time TIME)"; 

    private static final String CREATE_TABLE_SHOPPING_LIST = "create table if not exists shopping_list(" + 
      "_id INT PRIMARY KEY AUTOINCREMENT" + 
      "name TEXT" + 
      "quantity FLOAT)"; 

    private static final String CREATE_TABLE_PUBLIC_DB = "create table if not exists public_db(" + 
      "_id INT PRIMARY KEY AUTOINCREMENT" + 
      "name TEXT" + 
      "number INT)"; 

    private static final String CREATE_TABLE_CURRENT_CONTENTS = "create table if not exists current_contents(" + 
      "_id INT PRIMARY KEY AUTOINCREMENT" + 
      "name TEXT" + 
      "quantity FLOAT" + 
      "expiry DATE)"; 

    private final Context context; 
    private DatabaseHelper DBHelper; 
    private SQLiteDatabase db; 

    /** 
    * Constructor 
    * @param ctx 
    */ 
    public DBAdapter(Context ctx) 
    { 
     this.context = ctx; 
     this.DBHelper = new DatabaseHelper(this.context); 
    } 

    private static class DatabaseHelper extends SQLiteOpenHelper 
    { 
     DatabaseHelper(Context context) 
     { 
      super(context, DATABASE_NAME, null, DATABASE_VERSION); 
     } 

     @Override 
     public void onCreate(SQLiteDatabase db) 
     { 
      db.execSQL(CREATE_TABLE_RECIPES); 
      db.execSQL(CREATE_TABLE_SHOPPING_LIST); 
      db.execSQL(CREATE_TABLE_PUBLIC_DB); 
      db.execSQL(CREATE_TABLE_CURRENT_CONTENTS); 
     } 

     @Override 
     public void onUpgrade(SQLiteDatabase db, int oldVersion, 
           int newVersion) 
     { 
      // Adding any table mods to this guy here 
     } 
    } 

    /** 
    * open the db 
    * @return this 
    * @throws SQLException 
    * return type: DBAdapter 
    */ 
    public DBAdapter open() throws SQLException 
    { 
     this.db = this.DBHelper.getWritableDatabase(); 
     return this; 
    } 

    /** 
    * close the db 
    * return type: void 
    */ 
    public void close() 
    { 
     this.DBHelper.close(); 
    } 
} 

單個表適配器

package app.rory.pocket_chef.Adapters; 

import android.content.ContentValues; 
import android.content.Context; 
import android.database.Cursor; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 

import java.sql.SQLException; 

import app.rory.pocket_chef.Fragments.recipes_Fragment; 

/** 
* Created by Rory on 06/10/15. 
*/ 
    public class Recipes_Adapter { 

    public static final String ROW_ID = "_id"; 
    public static final String NAME = "name"; 
    public static final String INGREDIENTS = "ingredients"; 
    public static final String INSTRUCTIONS = "instructions"; 
    public static final String DESCRIPTION = "description"; 
    public static final String TIME = "time"; 

    private static final String DATABASE_TABLE = "recipes"; 

    private DatabaseHelper mDbHelper; 
    private SQLiteDatabase mDb; 

    private final Context mCtx; 

    private static class DatabaseHelper extends SQLiteOpenHelper { 

     DatabaseHelper(Context context) { 
      super(context, DBAdapter.DATABASE_NAME, null, DBAdapter.DATABASE_VERSION); 
     } 

     @Override 
     public void onCreate(SQLiteDatabase db) { 
     } 

     @Override 
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     } 
    } 

    /** 
    * Constructor - takes the context to allow the database to be 
    * opened/created 
    * 
    * @param ctx 
    *   the Context within which to work 
    */ 
    public Recipes_Adapter(Context ctx) { 
     this.mCtx = ctx; 
    } 

    /** 
    * Open the recipes database. If it cannot be opened, try to create a new 
    * instance of the database. If it cannot be created, throw an exception to 
    * signal the failure 
    * 
    * @return this (self reference, allowing this to be chained in an 
    *   initialization call) 
    * @throws SQLException 
    *    if the database could be neither opened or created 
    */ 
    public Recipes_Adapter open() throws SQLException { 
     this.mDbHelper = new DatabaseHelper(this.mCtx); 
     this.mDb = this.mDbHelper.getWritableDatabase(); 
     return this; 
    } 

    /** 
    * close return type: void 
    */ 
    public void close() { 
     this.mDbHelper.close(); 
    } 

    /** 
    * Create a new recipe. If the recipe is successfully created return the new 
    * rowId for that recipe, otherwise return a -1 to indicate failure. 
    * 
    * @param name 
    * @param ingredients 
    * @param instructions 
    * @param description 
    * @param time 
    * 
    * 
    * @return rowId or -1 if failed 
    */ 
    public long createRecipe(String name, String ingredients, String instructions, String description, String time){ 
     ContentValues initialValues = new ContentValues(); 
     initialValues.put(NAME, name); 
     initialValues.put(INGREDIENTS, ingredients); 
     initialValues.put(INSTRUCTIONS, instructions); 
     initialValues.put(DESCRIPTION, description); 
     initialValues.put(TIME, time); 
     return this.mDb.insert(DATABASE_TABLE, null, initialValues); 
    } 

    /** 
    * Delete the recipes with the given rowId 
    * 
    * @param rowId 
    * @return true if deleted, false otherwise 
    */ 
    public boolean deleteRecipe(long rowId) { 

     return this.mDb.delete(DATABASE_TABLE, ROW_ID + "=" + rowId, null) > 0; //$NON-NLS-1$ 
    } 

    /** 
    * Return a Cursor over the list of all recipes in the database 
    * 
    * @return Cursor over all recipes 
    */ 
    public Cursor getAllRecipes() { 

     return this.mDb.query(DATABASE_TABLE, new String[] { ROW_ID, 
       NAME, INGREDIENTS, INSTRUCTIONS, DESCRIPTION, TIME }, null, null, null, null, null); 
    } 

    /** 
    * Return a Cursor positioned at the recipe that matches the given rowId 
    * @param rowId 
    * @return Cursor positioned to matching recipe, if found 
    * @throws SQLException if recipe could not be found/retrieved 
    */ 
    public Cursor getRecipe(long rowId) throws SQLException { 

     Cursor mCursor = 

       this.mDb.query(true, DATABASE_TABLE, new String[] { ROW_ID, NAME, 
         INGREDIENTS, INSTRUCTIONS, DESCRIPTION ,TIME}, ROW_ID + "=" + rowId, null, null, null, null, null); 
     if (mCursor != null) { 
      mCursor.moveToFirst(); 
     } 
     return mCursor; 
    } 

    /** 
    * Update the recipe. 
    * 
    * @param rowId 
    * @param name 
    * @param ingredients 
    * @param instructions 
    * @param description 
    * @param time 
    * 
    * @return true if the note was successfully updated, false otherwise 
    */ 
    public boolean updateRecipe(long rowId, String name, String ingredients, String instructions, String description, String time){ 
     ContentValues args = new ContentValues(); 
     args.put(NAME, name); 
     args.put(INGREDIENTS, ingredients); 
     args.put(INSTRUCTIONS, instructions); 
     args.put(DESCRIPTION, description); 
     args.put(TIME, time); 

     return this.mDb.update(DATABASE_TABLE, args, ROW_ID + "=" + rowId, null) >0; 
    } 

} 

配方片段

package app.rory.pocket_chef.Fragments; 

import android.app.Fragment; 
import android.os.Bundle; 
import android.support.annotation.Nullable; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ListView; 

import java.sql.SQLException; 

import app.rory.pocket_chef.Adapters.DBAdapter; 
import app.rory.pocket_chef.Adapters.Recipes_Adapter; 
import app.rory.slidemenu.R; 

/** 
* Created by Z0NEN on 10/22/2014. 
*/ 
public class recipes_Fragment extends Fragment { 

    private Recipes_Adapter recipes; 
    private DBAdapter db; 


    View rootview; 
    @Nullable 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     rootview = inflater.inflate(R.layout.recipes_layout, container, false); 
     return rootview; 

    } 

    public void onActivityCreated (Bundle savedInstanceState) { 
     db = new DBAdapter(getActivity()); 
     recipes = new Recipes_Adapter(getActivity()); 
     try { 
      db.open(); 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

什麼錯誤?編譯時間錯誤? (如果是這樣,你應該回到學習Java的(OOP's)基礎知識)......在看了一下片段的類層次結構(參見片段文檔)之後,我沒有看到「Fragment」是Context的一個子類......並且關於如何在片段中獲取上下文的問題,其中要求bazillion次......當然,您應該知道片段的生命週期以獲取更多信息什麼是真實上下文 - 非空 – Selvin

+0

不是運行時錯誤。我更新了問題,指出發生錯誤的行號 – Hayes121

回答

1

我解決了這個問題,我試圖在創建片段之前訪問數據庫。我在onCreate()之後將下面的代碼添加到片段類中,並且它現在可以正常工作

public void onActivityCreated (Bundle savedInstanceState) { 
    db = new DBAdapter(getActivity()); 
    recipes = new Recipes_Adapter(getActivity()); 
    try { 
     db.open(); 
    } catch (SQLException e) { 
     e.printStackTrace(); 
    } 
} 
0

請看下面的代碼段:

構造分貝

public DatabaseHelper(Context context) { 
    super(context, DATABASE_NAME, null, DATABASE_VERSION); 
} 

構建數據庫對象

rootview = inflater.inflate(R.layout.recipes_layout, container, false); 
DatabaseHelper database = new DatabaseHelper(rootview.getContext()); 
return rootview; 

我不建議在適配器包裹的數據庫,我會建議單獨這些問題,以減少代碼糾纏。

+0

好的,謝謝你的建議,我會進行修改。你能告訴我如何去實例化碎片嗎? – Hayes121

+0

你的意思是[this](http://developer.android.com/training/basics/fragments/fragment-ui.html),你能澄清嗎? – caesiium

0

創建每個表...您錯過逗號來分隔每個字段。
這是你想要什麼:

//creating each table 
private static final String CREATE_TABLE_RECIPES = "create table if not exists recipes(" + 
     "_id INT PRIMARY KEY AUTOINCREMENT, " + 
     "name VARCHAR, " + 
     "ingredents TEXT, " + 
     "instructions TEXT, " + 
     "description TEXT, " + 
     "time TIME)"; 

private static final String CREATE_TABLE_SHOPPING_LIST = "create table if not exists shopping_list(" + 
     "_id INT PRIMARY KEY AUTOINCREMENT, " + 
     "name TEXT, " + 
     "quantity FLOAT)"; 

private static final String CREATE_TABLE_PUBLIC_DB = "create table if not exists public_db(" + 
     "_id INT PRIMARY KEY AUTOINCREMENT, " + 
     "name TEXT, " + 
     "number INT)"; 

private static final String CREATE_TABLE_CURRENT_CONTENTS = "create table if not exists current_contents(" + 
     "_id INT PRIMARY KEY AUTOINCREMENT, " + 
     "name TEXT, " + 
     "quantity FLOAT, " + 
     "expiry DATE)"; 

卸載並重新安裝你的應用程序得到數據庫重建。

+0

謝謝你,沒有注意到這一點。我正在採取多桌db的最佳方式嗎?我應該如何實例化碎片中的適配器? – Hayes121

+0

爲您的數據庫設置單獨的類。把所有的方法放在那裏,並用它們來填充適配器。簡單。 –

+0

對不起,不斷煩你,但我有興趣在這裏學習我的問題,我已經更新了問題,告訴我有問題,即使你能指出我正確的方向來修復它,這將是偉大的 – Hayes121