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