【发布时间】:2015-10-07 12:20:49
【问题描述】:
我正在尝试使用 Fragments 学习一些 Android 开发,但遇到了问题。
我的应用需要多个表,因此我采用了创建主数据库适配器的方法来创建所有表并为每个表命令使用单独的适配器。
我遇到的问题是在 recipe_Fragment 中实例化 recipe_Adapter 以访问适配器中的命令。
我需要更改一些内容以使上下文片段友好吗?
我认为将所有适配器分开更整洁,对吗?
将每个表的所有命令都放在一个大型主数据库适配器中会更好吗?
当我按照 Android Studio 的指示更改参数以适应 Fragment 时,我在以下行中收到错误;该错误表示找到了错误的第一个参数(即“上下文”)。
我曾尝试将其更改为 Fragment,但这给了我更多错误。
更新已解决!! 我将下面的片段类更改为工作版本。我试图在创建片段之前访问数据库,所以我试图传递一些不存在的东西。新代码在 try and catch 语句中的 onActivityCreated() 中访问数据库。
主数据库适配器 包 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)的基础知识)......在查看片段的类层次结构(参见片段文档)之后,我没有看到
Fragment是Context的子类......并且关于如何在 Fragment 中获取上下文的问题被问了无数次......当然你应该知道片段的生命周期以获得真正的上下文 - 不为空 -
不,不是运行时错误。我更新了指示发生错误的行的问题
标签: android sqlite android-fragments