Android学习之SQLite练习(一)
来源:互联网 发布:计算机加密软件 编辑:程序博客网 时间:2024/05/16 12:46
上次练习了ContentProvider,知道了一些基本原理,这次接着学习关于里面的SQLite部分。
这次练习的大致内容:SQLite的增,删,查询功能(这次是存放一个Programmer类的数据)。
大致实现思路:(借鉴了其他人的CSDN博客)
1.一个封装数据的Programmer类(包含,id,name,age,level,info信息)
2.数据库帮助管理类:DBHelpManager(继承自SQLiteOpenHelper类,里面负责数据库的创建以及更新,外部可以通过此类的getWritableDatabase()方法来创建或得到一个具有写入权限的SQLiteDatabase,通过getReadableDatabase()来得到一个具有读取权限的SQLiteDatabase)
3.一个数据库操作的规范接口SQLOperate:(里面声明一些对数据库的操作方法)
4.一个数据库操作的具体实现类SQLOperateEntity(实现SQLOperate接口):(具体定义数据库的增,删,查询等功能)
5.一个存放数据库操作的常量的类: SQLMetaData(里面定义一些静态常量,如数据库名,表名,表中的具体属性等)
6.测试所需的Activity:SqlDemoActivity(添加文本输入框,按钮,显示列表等,然后将按钮功能与具体数据库的操作绑定)
错误小结以及解决方法:
1.一些容易出错的 地方要常用try...exception(最好指明具体的错误类型,如SQLException).比如获取EditText里面的文本并且转换为int型时.
2.list<T>里面如果添加了一个null,那么在对List里面的成员进行具体操作时会出错。
未来展望:
1.这次的数据库是使用了OpenHelper类的自动创建方法,所以会创建在(data/data/packagename/)目录下,下次自己定义创建路径(SD卡)
方法(1.1):继承并重写ContextWrapper的方法,使得创建的时候自定义选择路径
方法(1.2):放弃使用OpenHelper,自定义数据库的创建,删除等操作方法
2.放弃使用OpenHelper类,自己定义数据库插入,删除等方法(灵活,而且可以用statement,事务支持等)
编程有感:一个小小的程序都得耗费N多时间。
总结:不积跬步无以至千里,继续努力吧!
10/28日更新内容:
1.完成了自定义数据库创建路径,通过继承ContextWrapper并改写Context行为
2.优化了EditText组件
新的工程路径:http://download.csdn.net/detail/u010979495/8091361
附录(关键代码以及效果图以及完整工程):
1.Programmer类
/**该类的作用是封装数据,与对应的表格相应*/public class Programmer { private int _id;//与所建立的表对应,与SQLite中的主键完全一致 private String name; private int age; private int level; private String info; public Programmer(int _id,String name,int age,int level,String info) { this._id=_id; this.name=name; this.age=age; this.level=level; if(info!=null) this.info=info; } //默认构造,全为空值 public Programmer() { this._id=0; this.name=""; this.age=0; this.level=0; this.info=""; } public int get_id() { return _id; } public void set_id(int _id) { this._id = _id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; }}
2.DBHelpManager类
/**数据库操作的帮助类*/public class DBHelpManager extends SQLiteOpenHelper{private static final String TAG="DBHelpManager";//定义创建数据库的SQL语句private static final String CREATE_TABLE="CREATE TABLE "+SQLMetaData.P1_TABLE_NAME+" ("+TableMetaData._ID+" INTEGER PRIMARY KEY, "+TableMetaData.PROGRAMMER_NAME+" TEXT, "+TableMetaData.PROGRAMMER_AGE+" INTEGER, "+TableMetaData.PROGRAMMER_LEVEL+" INTEGER, "+TableMetaData.PROGRAMMER_INFO+" TEXT"+");";public DBHelpManager(Context context) {super(context, SQLMetaData.DATABASE_NAME,null, SQLMetaData.DATABASE_VERSION);}//数据库第一次被创建时调用//会默认创建在"/data/data/packagename/"目录下@Overridepublic void onCreate(SQLiteDatabase db) {Log.i(TAG,"创建表:"+db.getPath());db.execSQL(CREATE_TABLE);}//版本升级时调用@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {Log.i(TAG,"更新数据库,从"+oldVersion+"到"+newVersion+",以前的数据会被销毁");//销毁的sql语句String sql="DROP TABLE IF EXISTS"+SQLMetaData.P1_TABLE_NAME;//执行db.execSQL(sql);//重新创建dbonCreate(db);}}
3.SQLOperate接口
/**定义一个SQLite操作规范的接口---采用接口单一原则*/public interface SQLOperate {public abstract void add(Programmer p);//只有id具有唯一性public abstract void delete(int id);public abstract void update(Programmer p);//查询,全部,单一public abstract List<Programmer> find();public abstract Programmer fingById(int id);}
4.SQLOperateEntity
/**数据库操作的具体类,实现操作规范的接口*/public class SQLOperateEntity implements SQLOperate{private static final String TAG="SQLOperateEntity";//数据库帮助对象的引用private DBHelpManager dbOpenHelper;/**构造方法*/public SQLOperateEntity(Context context){//产生一个DB帮助对象,里面创建一个SQLite数据库Log.i(TAG,TAG+"中创建数据库帮助类对象dbOpenHelper");dbOpenHelper=new DBHelpManager(context);}/** * 增,用insert向数据库中插入数据 */ @Overridepublic void add(Programmer p) {Log.i(TAG,TAG+"中插入数据");//其实在执行getWritableDatabase()时,dbOpenHelper会进行判定(打开还是创建数据库)SQLiteDatabase db=dbOpenHelper.getWritableDatabase();ContentValues values=new ContentValues();values.put(TableMetaData._ID,p.get_id());values.put(TableMetaData.PROGRAMMER_NAME, p.getName());values.put(TableMetaData.PROGRAMMER_AGE, p.getAge());values.put(TableMetaData.PROGRAMMER_LEVEL, p.getLevel());values.put(TableMetaData.PROGRAMMER_INFO, p.getInfo());//其实这种错误捕获方法是没用的,因为底层的SQLiteDatabase已经自动进行了错误捕获 db.insert(SQLMetaData.P1_TABLE_NAME, null, values);} /** * 删,通过id删除数据 */ @Overridepublic void delete(int id) {Log.i(TAG,TAG+"中删除数据");SQLiteDatabase db=dbOpenHelper.getWritableDatabase();String whereClause=TableMetaData._ID+"=?";//删除某个键值的判断String[] whereArgs=new String[]{String.valueOf(id)};//得到ID的stringdb.delete(SQLMetaData.P1_TABLE_NAME, whereClause, whereArgs);} /** * 改,修改指定id的数据 */ @Overridepublic void update(Programmer p) {Log.i(TAG,TAG+"中更新数据");SQLiteDatabase db=dbOpenHelper.getWritableDatabase();ContentValues values = new ContentValues(); values.put(TableMetaData._ID,p.get_id());values.put(TableMetaData.PROGRAMMER_NAME, p.getName());values.put(TableMetaData.PROGRAMMER_AGE, p.getAge());values.put(TableMetaData.PROGRAMMER_LEVEL, p.getLevel());values.put(TableMetaData.PROGRAMMER_INFO, p.getInfo());//根据id进行更新的String whereClause=TableMetaData._ID+"=?";//删除某个键值的判断String[] whereArgs=new String[]{String.valueOf(p.get_id())};//得到ID的stringdb.update(SQLMetaData.P1_TABLE_NAME, values, whereClause, whereArgs);} /** * 查,查询表中所有的数据 * 查询时不使用etWritableDatabase()而是ReadableDatabase() */ @Overridepublic List<Programmer> find() {Log.i(TAG,TAG+"中查询全部数据");List<Programmer> programmers=null;SQLiteDatabase db=dbOpenHelper.getReadableDatabase(); Cursor cursor=null;//得到整个表的Cursor cursor = db.query(SQLMetaData.P1_TABLE_NAME, null, null, null, null, null, null); if(cursor !=null) { programmers=new ArrayList<Programmer>(); //循环完所有的记录 for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()) { Programmer programmer=new Programmer(); //得到id的对应索引和值 int _id=cursor.getInt(cursor.getColumnIndex (TableMetaData._ID)); //得到name的对应索引和值 String name=cursor.getString(cursor.getColumnIndex (TableMetaData.PROGRAMMER_NAME)); //得到age的对应索引和值 int age=cursor.getInt(cursor.getColumnIndex (TableMetaData.PROGRAMMER_AGE)); //得到level的对应索引和值 int level=cursor.getInt(cursor.getColumnIndex (TableMetaData.PROGRAMMER_LEVEL)); //得到info的对应索引和值 String info=cursor.getString(cursor.getColumnIndex (TableMetaData.PROGRAMMER_INFO)); programmer.set_id(_id); programmer.setName(name); programmer.setAge(age); programmer.setLevel(level); programmer.setInfo(info); //添加进对应的list programmers.add(programmer); } }return programmers;} /** * 查询指定id的数据 */ @Overridepublic Programmer fingById(int id) {Log.i(TAG,TAG+"中查询单个数据:id="+id);SQLiteDatabase db=dbOpenHelper.getReadableDatabase();//得到某一条数据的CursorString selection=TableMetaData._ID+"=?";String[] selectionArgs=new String[]{String.valueOf(id)};Cursor cursor=null;try { cursor = db.query(SQLMetaData.P1_TABLE_NAME, null,selection, selectionArgs, null, null, null); } catch (Exception e) {Log.i(TAG,"单个查询错误!"+e.getMessage());} Programmer programmer=null; //只有一条记录 if(cursor!=null&&cursor.moveToFirst()) { programmer=new Programmer(); //得到id的对应索引和值 int _id=cursor.getInt(cursor.getColumnIndex (TableMetaData._ID)); //得到name的对应索引和值 String name=cursor.getString(cursor.getColumnIndex (TableMetaData.PROGRAMMER_NAME)); //得到age的对应索引和值 int age=cursor.getInt(cursor.getColumnIndex (TableMetaData.PROGRAMMER_AGE)); //得到level的对应索引和值 int level=cursor.getInt(cursor.getColumnIndex (TableMetaData.PROGRAMMER_LEVEL)); //得到info的对应索引和值 String info=cursor.getString(cursor.getColumnIndex (TableMetaData.PROGRAMMER_INFO)); programmer.set_id(_id); programmer.setName(name); programmer.setAge(age); programmer.setLevel(level); programmer.setInfo(info); } if(programmer==null) Log.i(TAG,"单个查询结果为空!");return programmer;}}
5.SQLMetaData
/**定义一些常用的量*/public class SQLMetaData {//数据库名public static final String DATABASE_NAME="Programmer_dlc.db";//版本号public static final int DATABASE_VERSION=1;//表名,一下是所有需要用到的表的名字public static final String P1_TABLE_NAME="ProgrammerTable";/**内部类,封装关于表的字段信息,实现BaseColumns接口 * 开发人员不必在定义字段_ID和_Count了(因为实现了BaseColumns) * static声明--只属于类而不是属于对象 * */public static final class TableMetaData implements BaseColumns{//某一个表中的所有属性的定义public static final String _ID="_id";//表中的主键public static final String PROGRAMMER_NAME="name";public static final String PROGRAMMER_AGE="age";public static final String PROGRAMMER_LEVEL="level";public static final String PROGRAMMER_INFO="info";//DESC(降序),ASC(升序),这句话的意思为按ID升序public static final String DEFAULT_SORT_ORDER=_ID+" ASC";}}
6.SqlDemoActivity
/**测试数据库操作的Activity*/public class SqlDemoActivity extends Activity implements OnClickListener{private static final String TAG="SqlDemoActivity";//数据库操作对象SQLOperateEntity sqlOperateEntity;private Button btn_insert;private Button btn_delete;private Button btn_query;private EditText edt_id;private EditText edt_name;private EditText edt_age;private EditText edt_level;private EditText edt_info;private ListView listViewContent;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.sqldemo_view);init();}/**功能函数*/private void init(){sqlOperateEntity=new SQLOperateEntity(this);bindWidgets();setListeners();}private void bindWidgets(){Log.i(TAG,"Widget绑定");edt_id=(EditText) findViewById(R.id.edt_id);edt_name=(EditText) findViewById(R.id.edt_name);edt_age=(EditText) findViewById(R.id.edt_age);edt_level=(EditText) findViewById(R.id.edt_level);edt_info=(EditText) findViewById(R.id.edt_info);btn_insert=(Button) findViewById(R.id.btn_insert);btn_delete=(Button) findViewById(R.id.btn_delete);btn_query=(Button) findViewById(R.id.btn_query);listViewContent=(ListView) findViewById(R.id.list_content);}private void setListeners(){Log.i(TAG,"设置监听函数");btn_insert.setOnClickListener(this);btn_delete.setOnClickListener(this);btn_query.setOnClickListener(this);}/**插入*/private void onInsert(Programmer p){Log.i(TAG,"开始插入数据");if(p.get_id()==-1&&p.getAge()==-1&&p.getLevel()==-1)//发现为默认数据时{Log.w(TAG,"没有输入数据,插入无效!");}else{sqlOperateEntity.add(p);}}/**删除*/private void onDelete(int _id){Log.i(TAG,"开始删除记录");sqlOperateEntity.delete(_id);}/**查询*/private List<Programmer> onQuery(int _id){List<Programmer> promrammers=new ArrayList<Programmer>();if(_id==-1)//默认为-1,代表查询全部{Log.i(TAG,"开始查询全部数据!");promrammers=sqlOperateEntity.find();}else{Log.i(TAG,"开始查询单条数据!");Programmer p;p=sqlOperateEntity.fingById(_id);if(p!=null)promrammers.add(p);elseLog.w(TAG,"没有查询到数据!");}return promrammers;}/**这里用到集合类的组合 * ArrayList<HashMap<String,Object>> * *//***/private void onRefreshView(List<Programmer> programmers){ if(!programmers.isEmpty()) {Log.i(TAG,"开始刷新查询数据!"); } else { Log.i(TAG,"空数据不能刷新查询!"); } List<HashMap<String, String>> items = onFillMaps(programmers); //查询添加到列表 ListAdapter listAdapter = new SimpleAdapter( this,items,R.layout.list, new String[]{"_id","name","age","level","info"}, new int[]{R.id.list_id,R.id.list_name, R.id.list_age,R.id.list_level,R.id.list_info}); listViewContent.setAdapter(listAdapter); }/**刷新*/private List<HashMap<String, String>> onFillMaps(List<Programmer> programmers){Log.i(TAG,"正在刷新查询数据!");List<HashMap<String, String>> items=new ArrayList<HashMap<String,String>>();//循环for(Programmer p:programmers){HashMap<String,String> map=new HashMap<String,String>();map.put("_id",String.valueOf(p.get_id()));map.put("name", p.getName());map.put("age",String.valueOf(p.getAge()));map.put("level",String.valueOf(p.getLevel()));map.put("info", p.getInfo());items.add(map);}return items;}@Overridepublic void onClick(View v) {int _id=-1;String name="";int age=-1;int level=-1;String info="";try { _id=Integer.parseInt(edt_id.getText().toString().trim()); name=edt_name.getText().toString().trim(); age=Integer.parseInt(edt_age.getText().toString().trim()); level=Integer.parseInt(edt_level.getText().toString().trim()); info=edt_info.getText().toString().trim();} catch (NumberFormatException e) {Log.i(TAG,"得到editText数据时出错!"+e.getMessage());}Programmer p=new Programmer(_id,name,age,level,info);switch(v.getId()){case R.id.btn_insert:onInsert(p);onRefreshView(onQuery(_id));break;case R.id.btn_delete:onDelete(_id);onRefreshView(onQuery(_id));break;case R.id.btn_query:onRefreshView(onQuery(_id));break;default:break;}}}
效果图1:(查询单条记录,程序里面填写好相应的ID)
效果图2:(查询全部记录,不填ID)
完整工程:http://download.csdn.net/detail/u010979495/8088497
- Android学习之SQLite练习(一)
- Android之SQLite 学习一
- Hello Android学习之SQLite(一)
- Android开发学习之SQLite详解一
- Android学习之HttpClient练习(一)
- Android学习之SQLite
- Android之SQLite学习
- Android学习之SQLite
- Android学习之SQLite
- Android学习之SQLite
- Android之SQLite学习
- Android学习之SQLite学习
- android学习笔记之SQLite
- Android学习 之 Sqlite小结
- Android学习笔记之SQLite
- Android学习笔记之SQLite
- Android之SQLite 学习二
- Android之SQlite学习小结
- hdu 3007 Buried memory (最小圆覆盖)
- TRIZ系列-创新原理-37-热膨胀原理
- 3ds max 扫盲
- POJ 2513 Colored Sticks (Trie字典树+欧拉通路+并查集) 解题报告
- 【软件工程】关于软件工程里需要熟悉的一些基本问题的讨论(一)
- Android学习之SQLite练习(一)
- 配置pydot环境
- bzoj 2818: Gcd
- PyMel技术集锦
- 我的第一个c++
- python中的函数
- HTTP Basic Authentication认证的资源的C#实现
- nyoj 79 拦截导弹
- Linux中weblogic中axis.jar的冲突的解决办法