前面一节中已经为Starbuzz创建了一个SQLite帮助器。
目前还是从Java Drink类获取数据,这时候要修改这个应用从SQLite数据库获取数据。
本文所有代码均存放于
https://github.com/MADMAX110/Starbuzz
基本步骤:
1、得到Starbuzz数据库的一个引用
2、创建一个游标从数据库读取数据
3、导航到饮料记录
4、在DrinkActiviy中显示饮料的详细信息
首先需要用上一章创建的SQLite帮助器得到Starbuzz数据库的一个引用。为此我们先要得到SQLite帮助器的一个引用。
SQLiteOpenHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
然后调用SQLite帮助器的getReadableDatabase() 或getWriteableDatabase() 得到数据库一个引用。前者只读,后者可以进行更新。这两者都会返回一个SQLiteDatabase对象,可以用来访问数据库。
SQLiteDatabase db = starbuzzDatabaseHelper.getReadableDatabase();
SQLiteDatabase db = starbuzzDatabaseHelper.getWritableDatabase();
如果Android没能得到数据库的一个引用,会抛出一个SQLiteExeception异常。例如,如果调用getWriteableDatabase来读写数据库,但是由于磁盘已满而无法写入数据库就会发生这种情况。
如果得到异常就可以使用一个Toast(一个弹出式消息)告诉用户这个消息不可用。
得到数据库的一个引用后,就可以使用游标从数据库中获取数据了。
创建游标
Cursor cursor = db.query(...);
最简单的数据库查询是从一个数据库的一个表中返回所有记录, 第一个参数是表名,第二个参数表示想要返回这些列中的值,如果想要返回一个表中的所有记录,将这些参数设置为null。
Cursor cursor = db.query("DRINK", new String[]{"_id", "NAME", "DESCRIPTION"}, null, null, null, null, null);
默认情况下,表中数据按_id的顺序显示,这是因为输入数据时的顺序。如果希望按NAME的升序顺序,可以使用以下代码。
Cursor cursor = db.query("DRINK", new String[]{"_id", "NAME", "DESCRIPTION"}, null, null, null, null, null, "NAME ASC");
ASC关键字表示你希望按升序对这一列排序。默认的都会按升序队列排序,所以也可以省略ASC,倘若要以降序排序则要使用DESC。
还可以对多个列进行排序,例如对FAVORITE降序排列,然后对NAME按升序排列。
Cursor cursor = db.query("DRINK", new String[]{"_id", "NAME", "DESCRIPTION"}, null, null, null, null, null, "FAVORITE DESC, NAME");
为数据设置过滤条件,返回特定的记录:例如返回DRINK列表中饮料名为Lattle的记录:
Cursor cursor = db.query("DRINK", new String[]{"_id", "NAME", "DESCRIPTION"}, "NAME = ?", new String[] {"Lattle"}, null, null, null);
或是DRINK列表中_id为1的记录:
Cursor cursor = db.query("DRINK", new String[]{"_id", "NAME", "DESCRIPTION"}, "_id = ?", new String[] {Integer.toString(1)}, null, null, null);
要从一个游标获取某个特定记录的值,首先要导航到这个记录。
游标主要有4个方法,这些方法分别是moveToFirst、moveToLast、moveToPrevious、moveToNext。
要返回游标的第一个记录可以使用moveToFirst方法,如果发现一个记录,这个方法就会返回一个true值。如果游标未返回任何记录就会返回false。
if (cursor.moveToFirst()){
}
同理、moveToLast是返回游标最后一个记录,moveToPrevious是前一个记录,moveToNext是后一个记录。
从第0列获取字符串,从第2列获取数值。
String name = cursor.getString(0);
int imageRes = cursor.getInt(2);
最后,关闭游标和数据库。
cursor.close();
db.close();
package com.hfad.starbuzz;
import androidx.appcompat.app.AppCompatActivity;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class DrinkActivity extends AppCompatActivity {
public static final String EXTRA_DRINKID = "drinkId";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink);
int drinkId = (Integer)getIntent().getExtras().get(EXTRA_DRINKID);
SQLiteOpenHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
try {
SQLiteDatabase db = starbuzzDatabaseHelper.getReadableDatabase();
Cursor cursor = db.query("DRINK",
new String[]{"NAME", "DESCRIPTION", "IMAGE_RESOURCE_ID"},
"_id = ?",
new String[] {Integer.toString(drinkId)},
null, null, null);
if (cursor.moveToFirst()) {
String nameText = cursor.getString(0);
String descriptionText = cursor.getString(1);
int photoId = cursor.getInt(2);
TextView name = (TextView) findViewById(R.id.name);
name.setText(nameText);
TextView description = (TextView) findViewById(R.id.description);
description.setText(descriptionText);
ImageView photo = (ImageView) findViewById(R.id.photo);
photo.setImageResource(photoId);
photo.setContentDescription(nameText);
}
cursor.close();
db.close();
}catch (SQLException e){
Toast toast = Toast.makeText(this,
"Database unavailable",
Toast.LENGTH_SHORT);
toast.show();
}
}
}
这里的步骤与之前的有所不同,因为这里要显示一个列表视图,它使用饮料数据作为它的数据源。我们要把这个数据的数据源转换为Starbuzz数据库,
1、创建一个游标从数据库读取饮料数据。
2、将列表视图的数组适配器替换为一个游标适配器。
第一步与之前的一样,这里需要做的是替换列表视图中的数组数据。
原理:
1、列表视图向适配器请求数据
2、适配器向游标请求数据库中的数据
3、适配器向列表视图返回数据
使用简单游标适配器的做法与使用数组适配器很类似:要初始化适配器,然后把它关联到列表视图。
SimpleCursorAdapter listAdapter = new SimpleCursorAdapter(this , //当前活动
android.R.layout.simple_list_item_1,//在列表视图中对应每一行显示一个值
cursor,//这是游标
new String[]{"NAME"},//使用游标的哪些列
new int[]{android.R.id.text1},//希望在那些视图中显示这些数据
0);//用来确定游标的行为,通常为0,这是默认值,也可以注册一个内容观察器
listDrinks.setAdapter(listAdapter);
修改后的DrinkCategoryActivity代码:
package com.hfad.starbuzz;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;
public class DrinkCategoryActivity extends AppCompatActivity {
private SQLiteDatabase db;
private Cursor cursor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink_category);
ListView listDrinks = (ListView) findViewById(R.id.list_drinks);
SQLiteOpenHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
try {
db = starbuzzDatabaseHelper.getReadableDatabase();
cursor = db.query("DRINK",
new String[]{"_id", "NAME"},
null, null, null, null, null);
SimpleCursorAdapter listAdapter = new SimpleCursorAdapter(this , //当前活动
android.R.layout.simple_list_item_1,//在列表视图中对应每一行显示一个值
cursor,//这是游标
new String[]{"NAME"},//使用游标的哪些列
new int[]{android.R.id.text1},//希望在那些视图中显示这些数据
0);//用来确定游标的行为,通常为0,这是默认值,也可以注册一个内容观察器
listDrinks.setAdapter(listAdapter);
}catch(SQLException e){
Toast toast = Toast.makeText(this, "Database unavailable", Toast.LENGTH_SHORT);
toast.show();
}
AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (position == 0) {
Intent intent = new Intent(DrinkCategoryActivity.this, DrinkCategoryActivity.class);
startActivity(intent);
}
Intent intent = new Intent(DrinkCategoryActivity.this, DrinkActivity.class);
//向意图增加所单击列表项的ID,第一个参数表示使用这个常量名表示意图中的额外信息名
//这样就能知道DrinkCategoryActivity和DrinkActivity在使用同一个字符串
//创建DrinkActivity活动时要增加这个常量。
intent.putExtra(DrinkActivity.EXTRA_DRINKID, (int)id);
startActivity(intent);
}
};
listDrinks.setOnItemClickListener(itemClickListener);
}
@Override
protected void onDestroy() {
super.onDestroy();
cursor.close();
db.close();
}
}