布局什么的先不说,昨天运行一个连接数据库的项目,手机上运行起来,每当点击一个复选框的时候,程序就会崩溃。
idea没有报出错误,我自己检查代码是看不出什么的,加断点调式。
加断点,点那个虫子
然后左下角点开Debug查看状态,运行程序,f8下一步,也可以在Android Monitor看到是values是null,定位到出错的地方。
点击下一步时候,没反应了,我使用了AsyncTask异步任务操作,总是自己中断调式。
然而搜搜并没有说异步调式怎么办。以后能学到再说。
不过这个小程序总算知道问题出在哪里了。还是异步任务那里。我在一个方法里面创建了一个对象,在第一个需要调用的子方法里面为它赋值,下一个子方法使用它。这里显示它是空的,所以程序运行时候崩溃。
原因竟然是我在第一个子方法立赋值时候重新定义了一遍。
导致全局的那个对象是被第二个子方法使用时候显示空值。
emmmmm
注意到一点就是如果在子方法里使用对象时候不要和全局对象重名。
还有俺们宇哥说的java编写规范,让我写“ = ”的时候两边加空格。好的。
接下来总结一下Android 数据库的小知识。
(一)这是创建数据库
1. SQLite 是一种文件数据库,使用代码可以完成数据库的操作功能。利用SQLiteDatabase类访问SQLite数据库。
2. 可以使用SQLite帮助器来创建和管理数据库。创建SQLite帮助器要扩展SQLiteOpenelper类。
3. 第一次使用数据库会执行Oncreate()方法创建一个数据库,使用SQLiteDatabase execSQL(String)方法执行SQL命令。数据库升级要调用onUpgrade()方法,所以这俩方法是必须的。
4. 数据库升级是通过查看版本号完成的,为了完成数据库的升级,把方法写出来在进行调用。
那个小列子创建数据库代码如下
class StarbuzzDatabaseHelper extends SQLiteOpenHelper{
private static final String DB_NAME="starbuzz";
private static final int DB_VERSION=2;//SQLite帮助器检查版本号
StarbuzzDatabaseHelper(Context context){
super(context,DB_NAME,null,DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db){
/* db.execSQL("CREATE TABLE DRINK("
+"_id INTEGER PRIMARY KEY AUTOINCREMENT,"
+"NAME TEXT,"
+"DESCRIPTION TEXT,"
+"IMAGE_RESOURCE_ID INTEGER);");
insertDrink(db,"Latte","Espresso with milk",R.drawable.latte);
insertDrink(db,"Cappuccino","Espresso hot milk",R.drawable.cappuccino);
insertDrink(db,"Filter","our best drip coffee",R.drawable.filter);*/
updataMyDatabase(db,0,DB_VERSION);
}
@Override
public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion){
updataMyDatabase(db,oldVersion,newVersion);
}
//做一个数据库升级方法
private void updataMyDatabase(SQLiteDatabase db,int oldVersion,int newVersion){
if(oldVersion<1){
db.execSQL("CREATE TABLE DRINK("
+"_id INTEGER PRIMARY KEY AUTOINCREMENT,"
+"NAME TEXT,"
+"DESCRIPTION TEXT,"
+"IMAGE_RESOURCE_ID INTEGER);");
insertDrink(db,"Latte","Espresso with milk",R.drawable.latte);
insertDrink(db,"Cappuccino","Espresso hot milk",R.drawable.cappuccino);
insertDrink(db,"Filter","our best drip coffee",R.drawable.filter);
}
if(oldVersion<2){
db.execSQL("ALTER TABLE DRINK ADD COLUMN FAVORITE NUMERIC");
}
}
//一个和插入的方法
private static void insertDrink(SQLiteDatabase db,String name,String description,int resourceId){
ContentValues drinkValues=new ContentValues();
drinkValues.put("NAME",name);
drinkValues.put("DESCRIPTION",description);
drinkValues.put("IMAGE_RESOURCE_ID",resourceId);
db.insert("DRINK",null,drinkValues);
}
}
(二)是连接数据库,抄一下小总结
1. 使用SQLiteDatabase query()创建游标,在底层,这回建立一个SQL SELECT 语句。然后利用这个游标来读写数据库。
2. getWritableDatabase()和getReadableDatabase()返回数据库对象,从写法可以看出来,前者支持读写,后者是只读,但后者是有有可能允许读写的,在不被允许的情况下才是只读功能。这个小程序使用前者容易造出数据库的不可访问引发程序bedug。
3. 获得数据库访问权限,取得数据当然是要利用起来的,不然干吗连接它,这里假设要取得数据并在listView显示,做法就是用一个使用游标的适配器CursorAdapter,实例化SimpleCursorAdapter用游标返回的值填充listView。
为真不懂得布局,不管了在这里放段代码吧。
public class DrinkCategoryActivity extends ListActivity {
//增加这些私有变量,以便关闭
private SQLiteDatabase db;
private Cursor cursor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_drink_category);
ListView listDrinks=getListView();
/*不再使用drink类的数组适配器填充,而选择使用游标 适配器
//用drinks数组填充列表试图
ArrayAdapter<Drink> listAdapter=new ArrayAdapter<Drink>(this,
android.R.layout.simple_list_item_1,
Drink.drinks);
listDrinks.setAdapter(listAdapter);*/
//使用游标获取饮品数据,在listView填充饮品列表
try{
//得到数据库的引用
SQLiteOpenHelper starbuzzDatabaseHelper =new StarbuzzDatabaseHelper(this);
//从数据库读取数据
db=starbuzzDatabaseHelper.getReadableDatabase();
//游标必须包含_id列,
cursor=db.query("DRINK",
new String[]{"_id","NAME"},
null,null,null,null,null);
//创建一个游标适配器,显示name列内容
CursorAdapter listAdapter=new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1,
cursor,
new String[]{"NAME"},
new int[]{android.R.id.text1},
0);
//使用这个游标适配器
listDrinks.setAdapter(listAdapter);
}catch (SQLException e){
Toast toast =Toast.makeText(this,"Database unavailable",Toast.LENGTH_SHORT);
toast.show();
}
}
//在这个方法中关闭游标和数据库,游标会一直保持打开,知道适配器不再需要为止
@Override
public void onDestroy(){
super.onDestroy();
cursor.close();
db.close();
}
@Override
public void onListItemClick(ListView listView, View view,int position,long id){
Intent intent=new Intent(DrinkCategoryActivity.this,DrinkActivity.class);
intent.putExtra(DrinkActivity.EXTRA_DRINKNO,(int) id);
startActivity(intent);
}
}
ohno。。怎么这么乱。
4. 比如主界面有个更新,那么返回界面时候就希望看到有更新,但是游标只在创建时候获取数据,要使用changeCursor()把游标适配器替换为提供一个新目标,在返回时候活动中再取数据。然后关闭原来的游标。
5. 记得最后游标和数据库都要关闭。
一些抄来的代码如下
public class TopLevelActivity extends AppCompatActivity {
//创建私有变量以便关闭在onDstory
private SQLiteDatabase db;
private Cursor favoriteCursor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_top_level);
//床卷一个监听
AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> listView, View v, int position, long id) {
if (position == 0) {
Intent intent = new Intent(TopLevelActivity.this, DrinkCategoryActivity.class);
startActivity(intent);
}
}
};
//关联到listView
ListView listView = (ListView) findViewById(R.id.list_options);
listView.setOnItemClickListener(itemClickListener);
//得到favorite列表视图
ListView listFavorites = (ListView) findViewById(R.id.list_favorites);
try {
SQLiteOpenHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
db = starbuzzDatabaseHelper.getReadableDatabase();
favoriteCursor = db.query("DRINK",
new String[]{"_id", "NAME" },
"FAVORITE=1",
null, null, null, null);
//在游标适配器中使用游标,显示name列
CursorAdapter favoriteAdapter = new SimpleCursorAdapter(TopLevelActivity.this,
android.R.layout.simple_list_item_1,
favoriteCursor,
new String[]{"NAME" },
new int[]{android.R.id.text1},
0);
//使用这个游标适配器
listFavorites.setAdapter(favoriteAdapter);
} catch (SQLiteException e) {
Toast toast = Toast.makeText(this, "Database unavailable", Toast.LENGTH_SHORT);
toast.show(); }
//如果点击列表视图就调用此方法
listFavorites.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
//单击favorite list 中的一项,常见一个意图,启动DrinkActivity并传入这个饮品的id
public void onItemClick(AdapterView<?> ListView, View v, int position, long id) {
Intent intent = new Intent(TopLevelActivity.this, DrinkActivity.class);
intent.putExtra(DrinkActivity.EXTRA_DRINKNO, (int) id);
startActivity(intent);
}
});
}
@Override
public void onDestroy () {
super.onDestroy();
favoriteCursor.close();
db.close();
}
//怎么刷新数据游标
public void onRestart(){
super.onRestart();
try {
StarbuzzDatabaseHelper starbuzzDatabaseHelper=new StarbuzzDatabaseHelper(this);
db=starbuzzDatabaseHelper.getReadableDatabase();
Cursor newCursor=db.query("DRINK",
new String[]{"_id","NAME"},
"FAVORITE=1",
null,null,null,null);
ListView listFavorite=(ListView)findViewById(R.id.list_favorites);
CursorAdapter adapter=(CursorAdapter) listFavorite.getAdapter();
//将游标适配器 当前多使用的游标 替换为新游标
adapter.changeCursor(newCursor);
favoriteCursor=newCursor;
}catch (SQLiteException e) {
Toast toast = Toast.makeText(this, "Database unavaiable", Toast.LENGTH_SHORT);
toast.show(); }
}
}
什么什么阿 日常加油!