设为首页 收藏本站
查看: 1261|回复: 0

[经验分享] Android学习笔记(四二):SQLite、ListView、ContextMenu

[复制链接]

尚未签到

发表于 2016-12-1 08:59:38 | 显示全部楼层 |阅读模式
继续上一个例子,结合ListView中对SQLite进行操作。
通过CursorAdapter在ListView中的数据呈现
在上一个例子中,我们可以对SQLite中的数据库进行增删改查,将数据读到游标Cursor中,然后一一读出。在Android中可以通过CursorAdapter直接将数据映射到ListView中,如下处理:
DSC0000.png public class Chapter22Test1 extends ListActivity{
private SQLiteDatabase db = null;
private Cursor cursor = null;

private SimpleCursorAdapter adapter = null;

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
db= (new Chapter22Db (getApplicationContext())).getWritableDatabase();
cursor =db.rawQuery("SELECT _id,Name,Weight from mytable ORDER BY Weight", null);
  //layout/chapter_22_test1.xml的Android XML文件定义了ListView中每个单元的排列方式,每个单元R.id.c22_name和R.id.c22_gravity都是TextView,分列左右
adapter = new SimpleCursorAdapter(this,
R.layout.chapter_22_test1,
cursor,
new String[]{"Name","Weight"},//游标数据的名称,实际是Table列名字
new int[]{R.id.c22_name,R.id.c22_gravity});//对应的UI微件的id
setListAdapter(adapter);
}

protected void onDestroy() {
  super.onDestroy();
cursor.close(); //我们在onCreate()中没有关闭游标,因为需要和ListView进行数据关联,关闭curosr,会导致List无数据,故在最后释放资源
db.close(); //断开和数据库的连接,释放相关资源
}
}

更新数据(以增加为例)
我们要实现:通过Menu弹出菜单,有一个为增加,按之,弹出一个Dialog,可以在当中填入数据,按Dialog的确定按键,在SQLite数据库的表格mytable中加入相关的数据,并且同步ListView的显示。
第一步:建立OptionsMenu,里面有菜单“Add”,按键后,触发执行add()的操作。具体实现不在此罗嗦,可以参见Android学习笔记(八):Activity-OpenMenu和LinearLayout
第二步:在add()中,要完成弹出指定格式的Dialog,采用AlertDialog的方式,Dialog的格式在xml中给出。处理方式之前都学过,但是没有合并使用的例子,包括Dialog的格式,同ListView中自定义元素的格式一样,采用LayoutInflater。具体如下:
DSC0001.png private void add(){
//步骤2.1:通过LayoutInflater从Android的XML文件中生成View
LayoutInflater inflater = LayoutInflater.from(this);
final View addView = inflater.inflate(R.layout.add_dialgo,null);

//步骤2.2:通过AlertDialog弹出对话框,并且在第一个button,即PositiveButton监听事件,触发操作
new AlertDialog.Builder(this)
.setTitle("添加框")
.setView(addView)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
  //我们希望得到addView中的数据,但是这个inner class,只能获取final的值,所以之前将addView设置为final,也就是所有addView的地址是固定的,而不是动态生成。
public void onClick(DialogInterface dialog, int which) {
   EditText nameView = (EditText)addView.findViewById(R.id.c22_name);
EditText weigthView = (EditText)addView.findViewById(R.id.c22_weight);

// addData是下面步骤三,实现SQLite的数据更新和ListView的显示同步add(name,weight);
addData(nameView.getText().toString(), new Float(weigthView.getText().toString()).floatValue());
}
})
.setNegativeButton("取消",null)
.show();
}

第三步:更新数据库和同步ListView,具体如下:
DSC0002.png private void addData(String name ,float weight){
/* 略去数据的判断,例如如果name一样,采用update的方式等等*/
//步骤3.1 在数据库表格中添加数据

ContentValues values = new ContentValues(2);
values.put("Name",name);
values.put("Weight",weight);
db.insert("mytable","Name",values);
//步骤3.2 同步ListView,更新游标的信息
cursor.requery();
}
异步后台同步数据
在上面的例子,貌似可以,而且的确是可以,但是在Android的API文档中,Cursor的方法requery()这样写道:This method is deprecated.Don't use this. Just request a new cursor, so you can do this asynchronously and update your list view once the new cursorcomes back. 这提示我们风险的存在,如果数据量大,会导致重写读取的事件长(也就是requery()的执行时间)。虽然手机是人手操作,互动频率较低,在数据库数据少的时候,例如上面的例子,我们仍然可以安全地使用requery。但是对于具有大量数据时,我们就需要修改上面的程序。
修订的方式步骤如下:1,通过后台线程来读取数据库;2、通过更换cursor来更新ListView,具体如下:

//步骤1:通过后台线程AsyncTask来读取数据库,放入更换Cursor
private class RefreshList extends AsyncTask<Void, Void ,Cursor>{
//步骤1.1:在后台线程中从数据库读取,返回新的游标newCursor
protected Cursor doInBackground(Void... params) {
Cursor newCursor = db.rawQuery("SELECT _id,Name,Weight from mytable ORDER BY Weight", null);
return newCursor;
}
//步骤1.2:线程最后执行步骤,更换adapter的游标,并奖原游标关闭,释放资源
protected void onPostExecute(Cursor newCursor) {
adapter.changeCursor(newCursor);//网上看到很多问如何更新ListView的信息,采用CusorApater其实很简单,换cursor就可以
cursor.close();
cursor = newCursor;
}  
}
//步骤2:取缔requrey的方式,采用后台线程更新形式
private void addData(String name ,float weight){
... ...
//cursor.requery();
new RefreshList().execute();
}

通过ContextMenu来删除ListView的数据

ContextMenu用户手指长按某个View触发的菜单,见Android 学习笔记(二七):Menu。这里通过这个例子详细展开。实现场景:用户长按某个List元素,则弹出ContextMenu,选择菜单“Delete”,按下后,弹出AlertDialog,请用户再去确定是否删除,确定后将数据从SQLite中删除,并更新ListView的显示。具体如下:
DSC0003.png

DSC0004.png

DSC0005.png
protected void onCreate(Bundle savedInstanceState) {
... ...
//步骤1:向ListView注册Context Menu,当系统检测到用户长按某单元是,触发Context Menu弹出
registerForContextMenu(getListView());
}

// 步骤2:创建ContextMenu同OptionMenu,用户长按元素后,会弹出菜单

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
menu.add(Menu.NONE,DELETE_ID,Menu.NONE,"Delete");
super.onCreateContextMenu(menu, v, menuInfo);
}

//步骤 3: ContextMenu的触发操作,例子将触发delete()
public boolean onContextItemSelected(MenuItem item) {
switch(item.getItemId()){
case DELETE_ID:
/* 在此处,我们关键引入 AdapterView.AdapterContextMenuInfo来获取单元的信息。在有三个重要的信息。 1、id:The row id of the item for which the context menu is being displayed ,在cursorAdaptor中,实际就是表格的_id序号; 2、position 是list的元素的顺序;3、view就可以获得list中点击元素的View,通过view可以获取里面的显示的信息  */

AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
delete(info.id);
   return true;
default:
break;

}
return super.onContextItemSelected(item);
}

//步骤4: 对触发弹框,和Add的相似,确定后,更新数据库和更新ListView的显示,上次学习已有相类的例子,不再重复。其中getNameById是通过id查名字的方法。值得注意的是,为了内部类中使用,delete的参数采用来final的形式。
private void delete(final long rowId){
if(rowId>0){
newAlertDialog.Builder(this)
   .setTitle("删除" + getNameById(rowId))
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
deleteData(rowId);
}
})
.setNegativeButton("取消", null)
.show();

}
}

private void deleteData(long rowId){
  String[] str = {String.valueOf(rowId)};
db.delete("mytable","_id=?",str);

new RefreshList().execute(); //采用后台方式,当然也可以用crusor.requery()来处理。
}

通过模拟器的Console进行数据库操作

通过android-sdk-linux_x86/platform-tools目录下面有adb命令,使用adb shell,可提供模拟器的console窗口。数据库文件存放的位置为/data/data/your.app.package/databases/your-db-name,进入相关的目录,可以使用#sqlite3your-db-name,进入相关的数据库,可以在里面执行SQL语句,例如在整个例子中,通过#.schema来查看表格的格式,通过#select * from mytable;可以显示数据库的内容。

相关链接:我的Andriod开发相关文章

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-307962-1-1.html 上篇帖子: Android 开发中使用 SQLite 数据库之一 下篇帖子: Android数据存储访问方式-SQLite,ContentProvider的应用
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表