android操作sqlite数据库及心得
写这篇文章主要是网上的对sqlite的操作太多且太杂,非常多时候都不能非常好的运用到自己的项目中,结构不清晰,我自己写了一篇适合刚刚接触的人看的操作方法。
近来用android时要将一些数据保存起来,一開始用的是preferences,后来要保存的东西多了。发现用preferences明显不能满足要求了,并且发现用这个的话代码就变得有点乱了。所以才開始学习使用sqlite数据库,一開始以为不就是个数据库么,和平时的mysql啊或者是sqlserver都一样。都非常easy的,但后来真正在用的时候才发现困难一个接着一个。但还是在不断的摸索中一步一步的不断解决困难。后来发现学习安卓的话当自己实在找不到思路时看看网上的一些教学视频也是个不错的选择。这里推荐一个视频不错,我就是照这个视频学的。
http://www.tudou.com/programs/view/2qH5Am_3MsM/
写一下android操作数据库中的一些准备。
首先,配一下adb的环境变量,由于每次都要到adb的文件夹下去启动实在太麻烦了,以下是详细步骤。当然也能够该其它文件,我习惯改这个。能够改完后能够source一下使它生效。
1、sudo gedit /etc/profile
2、将以下的两句加到上面打开的文件中
export ANDROID_HOME=/home/sdk文件路径
export PATH=$PATH:$ANDROID_HOME/platform-tools
3、重新启动电脑,大功告成!!
adb配好以后,我们最好还要给手机里的数据库訪问的权限。一般在/data/data/包名/database 里面,用adb shell进入后su获得手机root权限,然后给权限chmod。
要读数据库文件的话就用命令 sqlite3 数据库文件 ,当中的数据库能够直接在adb shell中执行sqlite3,但我依照网上弄的就是不能在adb shell中打开sqlite3数据库。说命令没有找到,我该传的文件都传了。没办法。仅仅有在eclipse里的ddms的file explore里把数据库文件到处然后在linux终端里执行sqlite3数据库来看了。
还有要注意的是写sql语句时一定要注意"select * from " +TABLE_NAME 中的from和引號要留有空格。不然的话就连在一起了。
以下的有一个知识要讲一下,sqlite的添加,删除等操作都挺简单的,麻烦的就是查询操作,一般都借用Cursor来保存查询数据,一開始我没怎么注意这是一个指针类型,指向数据库里的数据。而我一開始写的时候把数据库的关闭操作写在了Cursor操作的前面。也就是说先把数据库关闭了再对Cursor对象进行操作。这种话就造成了Cursor的空指针,也就注定杯具了好久。。。
以下就贴一些关于sqlite数据库操作的事例,这样对一些还在困惑中的人有一些帮助。同一时候有助于以后自己回想。
SQLiteHelper.java(数据库辅助类)
public class SQLiteHelper extends SQLiteOpenHelper{ private static final String DATABASE_NAME="fpp.db";
private static final int DATABASE_VERSION=17;//更改版本号后数据库将又一次创建
private static final String TABLE_NAME="test"; /**
* 在SQLiteOpenHelper的子类其中。必须有这个构造函数
* @param context 当前的Activity
* @param name 表的名字(而不是数据库的名字,这个类是用来操作数据库的)
* @param factory 用来在查询数据库的时候返回Cursor的子类,传空值
* @param version 当前的数据库的版本号,整数且为递增的数
*/
public SQLitedata(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);//继承父类
// TODO Auto-generated constructor stub
}
/**
* 该函数是在第一次创建数据库时运行。仅仅有当其调用getreadabledatebase()
* 或者getwrittleabledatebase()并且是第一创建数据库是才会运行该函数
*/ public void onCreate(SQLiteDatabase db)
{ // TODO Auto-generated method stub
String sql = "CREATE TABLE " + TABLE_NAME + "("
+ "id INTEGER,"
+ "nid VARCHAR(11),"
+ "sid CHAR(1),"
+ "type INTEGER,"
+ "stime DATETIME,"
+ "locate_main VARCHAR(45),"
+ "locate_detail VARCHAR(45),"
+ "state INTEGER"
+ ")";
db.execSQL(sql);
Log.e("create","数据库创建成功");
}
/**
*数据库更新函数。当数据库更新时会运行此函数
*/ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
String sql = "DROP TABLE IF EXISTS " + TABLE_NAME;
db.execSQL(sql);
this.onCreate(db);
// TODO Auto-generated method stub
System.out.println("数据库已经更新");
/**
* 在此加入更新数据库是要运行的操作
*/
} }
MyOperator.java (数据库操作类)
public class MyOperator { private static final String TABLE_NAME = "test";//要操作的数据表的名称
private SQLiteDatabase db=null; //数据库操作 //构造函数
public MyOperator(SQLiteDatabase db)
{
this.db=db;
} // //插入操作
// public void insert(int id,String nid,String sid,int type,
// String stime,String etime,String desc,String locate_main,String locate_detail,int state)
// {
// String sql = "INSERT INTO " + TABLE_NAME + " (id,nid,sid,type,stime,etime,desc,locate_main,locate_detail,state)"
// + " VALUES(?,?,?,? ,? ,? ,? ,?,?,? )";
// Object args[]=new Object[]{id,nid,sid,type,stime,etime,desc,locate_main,locate_detail,state};
// this.db.execSQL(sql, args);
// this.db.close();
// }
//插入重载操作
public void insert(int id,int state)
{
String sql = "INSERT INTO " + TABLE_NAME + " (id,state)" +" VALUES(?,? )";
Object args[]=new Object[]{id,state};
this.db.execSQL(sql, args);
this.db.close();
} //更新操作
public void update(int id,int state)
{
String sql = "UPDATE " + TABLE_NAME + " SET state=? WHERE id=?";
Object args[]=new Object[]{state,id};
this.db.execSQL(sql, args);
this.db.close();
} //删除操作,删除
public void delete(int id)
{
String sql = "DELETE FROM " + TABLE_NAME +" WHERE id=?";
Object args[]=new Object[]{id};
this.db.execSQL(sql, args);
this.db.close();
} //查询操作,查询表中全部的记录返回列表
public List<String> find()
{
List<String> all = new ArrayList<String>(); //此时仅仅是String
String sql = "SELECT * FROM " + TABLE_NAME;
Cursor result = this.db.rawQuery(sql, null); //运行查询语句
for(result.moveToFirst();!result.isAfterLast();result.moveToNext() ) //採用循环的方式查询数据
{
all.add(result.getInt(0)+","+result.getString(1)+","+result.getString(2)+","+result.getInt(3)+","
+result.getString(4)+","+result.getString(5)+","+result.getString(6)+","+result.getString(7)+","
+result.getString(8));
}
this.db.close();
return all;
} //查询操作虫重载函数,返回指定ID的列表
public int getstatebyID(int id)
{
int num=-1;//错误状态-1
List<String> all = new ArrayList<String>(); //此时仅仅是String
String sql = "SELECT state FROM " + TABLE_NAME + " where id=?" ;
String args[] = new String[]{String.valueOf(id)};
Cursor result = this.db.rawQuery(sql, args);
for(result.moveToFirst();!result.isAfterLast();result.moveToNext() )
{
num=result.getInt(0);
} Log.e("database", "图片状态state"+ String.valueOf(num));
this.db.close();
return num;
} //推断插入数据的ID是否已经存在数据库中。 public boolean check_same(int id)
{
String sql="SELECT id from " + TABLE_NAME + " where id = ?";
String args[] =new String[]{String.valueOf(id)};
Cursor result=this.db.rawQuery(sql,args);
Log.e("database", "the sql has been excuate"); Log.e("database","the hang count" + String.valueOf(result.getCount())); if(result.getCount()==0)//推断得到的返回数据是否为空
{
Log.e("database", "return false and not exist the same result" + String.valueOf(result.getCount()));
this.db.close();
return false;
}
else
{
Log.e("database", "return true and exist the same result"+ String.valueOf(result.getCount()));
this.db.close();
return true;
}
}
}
随便的一个项目中的activity(activity 类。操作打开数据库已经在里面)
public class MainActivity extends Activity {
private static LinkedList<Map<String, Object>> mListItems;
private PullToRefreshListView pullToRefreshListView;
private ProblemController problemController = ProblemController.getInstance(); private SQLiteOpenHelper helper =null;
private MyOperator mytab=null; /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.helper=new SQLitedata(this);//数据库操作辅助类
setPullToRefreshView();
} @Override
public boolean onCreateOptionsMenu(Menu _menu){
super.onCreateOptionsMenu(_menu);
_menu.add(0, 0, 0, "设置");
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem _item){
switch (_item.getItemId()) {
case 0:{
Intent intent = new Intent(getApplicationContext(), SettingsActivity.class);
startActivity(intent);
break;
}
}
return true;
} private class GetDataTask extends AsyncTask<Void, Void, String[]> { @Override
protected String[] doInBackground(Void... params) {
if(listToShowData(problemController.getNewProblems())){ }else {
Message message = new Message();
handler.sendMessage(message);
}
return mStrings;
} @Override
protected void onPostExecute(String[] result) {
pullToRefreshListView.onRefreshComplete();
super.onPostExecute(result);
}
} private String[] mStrings = {}; /**
* @param _newslist 须要显示的消息列表
*/
private boolean listToShowData(LinkedList<Problem> _problems) {
if(_problems != null){
mListItems.clear();
for (Problem news : _problems) {
//将数据插入数据库进行初始化
//这里须要一个推断反复的操作。假设数据的id已经在数据库中就不须要进行插入数据 mytab = new MyOperator(helper.getWritableDatabase());
Log.e("database", "start check if id exists and insert the id,the id is "+String.valueOf(news.getID()));
if(!mytab.check_same(news.getID()))
{
Log.e("database", "the id is not exist,insert the new id now.....");
mytab = new MyOperator(helper.getWritableDatabase());
mytab.insert(news.getID(), 1);
Log.e("database", "insert finished");
} Map<String, Object> tmpMap = new HashMap<String, Object>(); //用来储存日志名称的Map
tmpMap.put("id", news.getID());
tmpMap.put("describe", "模块:" + news.getSid() + "出现故障!");
tmpMap.put("time", news.getsTime());
tmpMap.put("img", R.drawable.icon_important); Log.e("database", "start read database"); //读取数据库推断这个事件的状态显示相应的图标,1表示默认状态问号,2表示已察看。3表示事件已经完毕勾
mytab = new MyOperator(helper.getWritableDatabase());
int state = mytab.getstatebyID(news.getID());
switch(state)
{
case 1:tmpMap.put("state_img", R.drawable.icon_question);break;
case 2:tmpMap.put("state_img", R.drawable.icon_process);break;
case 3:tmpMap.put("state_img", R.drawable.icon_correct);break;
default:tmpMap.put("state_img", R.drawable.icon_correct);
}
mListItems.add(tmpMap);
Log.e(news.toString(), news.toString());
}
return true;
}else {
return false;
}
} /**
* @param 对下拉刷新控件进行设置
*/
private void setPullToRefreshView(){
mListItems = new LinkedList<Map<String,Object>>();
pullToRefreshListView = (PullToRefreshListView)findViewById(R.id.pullToRefreshListView1);
pullToRefreshListView.setOnRefreshListener(new OnRefreshListener() {
public void onRefresh() {
new GetDataTask().execute(); //拉数据的线程开启
}
});
pullToRefreshListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, final int arg2,
long arg3) {
Log.e("Pull", String.valueOf(arg2));
ShareData.showProblem = problemController.getOldProblems().get(arg2 - 1);
Intent intent = new Intent(getApplicationContext(), DetailsActivity.class); //设置新的图片,如今用数据库的方法,所以这个操作就不须要了,到时候统一读取图片
// ImageView tempImage=(ImageView)arg1.findViewById(R.id.imageView2);
// tempImage.setImageResource(R.drawable.icon_correct);
//把状态存入数据库,推断图片状态,假设为1则说明没有被訪问过。改变为2
mytab = new MyOperator(helper.getWritableDatabase());
if(mytab.getstatebyID(ShareData.showProblem.getID())==1)
{
mytab = new MyOperator(helper.getWritableDatabase());
mytab.update(ShareData.showProblem.getID(), 2);
} //将故障ID传入到选项界面。以便与推断哪个页面选了哪些选项。 int id=ShareData.showProblem.getID();
Bundle bd=new Bundle();
bd.putInt("id", id);
intent.putExtra("ID", bd); startActivity(intent);
//传入到了还有一个界面
}
});
pullToRefreshListView.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<? > arg0, View arg1,
int arg2, long arg3) {
Log.e("PullLong", String.valueOf(arg2));
return true;
}
});
SimpleAdapter adapter = new SimpleAdapter(getApplicationContext(), mListItems, R.layout.layout_listitem,
new String[]{"id", "img", "describe", "time" ,"state_img"},
new int[]{R.id.title_TV, R.id.imageView1, R.id.content_TV, R.id.date_TV, R.id.imageView2});
pullToRefreshListView.setAdapter(adapter); } private Handler handler = new Handler(){
@Override
public void handleMessage(Message message) {
Toast.makeText(getApplicationContext(), "网络状况出现故障!", Toast.LENGTH_LONG).show();
}
};
}
android操作sqlite数据库及心得的更多相关文章
- 无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)
1.android下junit测试框架配置 单元测试需要在手机中进行安装测试 (1).在清单文件中manifest节点下配置如下节点 <instrumentation android:name= ...
- Android中操作SQLite数据库
我又回到了安卓的学习当中,忙来忙去终于忙的差不多有时间做自己的事情了,这感觉实在是太棒了!!本来想写android的控件以及他们的监视器的,但是我查了查android的手册,基本上都能查到,但是查有些 ...
- Android中SQLite数据库操作(1)——使用SQL语句操作SQLite数据库
下面是最原始的方法,用SQL语句操作数据库.后面的"Android中SQLite数据库操作(2)--SQLiteOpenHelper类"将介绍一种常用的android封装操作SQL ...
- Java操作Sqlite数据库-jdbc连接
Java操作Sqlite数据库步骤: 1. 导入Sqlite jdbc 本文使用sqlite-jdbc-3.7.2.jar,下载地址 http://pan.baidu.com/s/1kVHAGdD 2 ...
- android 一个SQLite数据库多个数据表的基本使用框架 (带demo)
android 一个SQLite数据库多个数据表(带demo) 前言 demo演示 一.搭建 二.建立实体类 三.建立数据库操作类 ...
- Qt for Android 打包 SQLite 数据库
Qt for Android 调用 SQLite 数据库时, 怎样将已经存在的数据库附加到 APK 中? 直接在你项目里面的Android源码的根目录下新建一个文件夹assets, 数据库就可以放里面 ...
- Android实现SQLite数据库联系人列表
Android实现SQLite数据库联系人列表 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 工程内容 实现一个通讯录查看程序: 要求使用SQLite ...
- EF6操作Sqlite数据库的项目兼容性问题
vs2010无法正确打开2015创建的项目里面操作Sqlite数据库时使用EF6创建的edmx文件(会显示空白) 但是可以正常查询 vs2015无法正确打开2010创建的项目里面操作Sqlite数 ...
- EF操作sqlite数据库时的项目兼容性问题
问题:vs2015打不开vs2010建的操作sqlite的实体数据模型edmx文件 原因: 当前电脑必须先安装:驱动库及sqlite的vs拓展 正常情况下安装驱动和拓展后,vs2015就应该可以正常打 ...
随机推荐
- if语句引起的bug
最近维护高手留下的api项目,客户端反馈一个bug过来,然后查找到可能出错的代码位置,是一个if语句,乍一看好像没什么问题,代码如下: if (company.UserId != userId || ...
- 页面跳转时中间参数保存(memcache/cookie)
2014年1月19日 17:30:27 我这篇文章就说了一句话:用cookie保存页面间跳转时的参数 情景: 客服在后台操作的时候,经常从列表页进入到编辑页,编辑完信息后,还要自动返回之前的列表页 问 ...
- 09 Go 1.9 Release Notes
Go 1.9 Release Notes Introduction to Go 1.9 Changes to the language Ports ppc64x requires POWER8 Fre ...
- 【前端开发】移动端适配方案js,rem单位转换,640设计稿20px=1rem
! function() { var style = document.createElement("STYLE"), docEl = document.documentEleme ...
- SqlServer中 CREATE PARTITION FUNCTION使用
表分区的操作三步走: 1.创建分区函数 CREATE PARTITION FUNCTION xx1(int) 解释:在当前数据库中创建一个函数,该函数可根据指定列的值将表或索引的各行映射到分区. 语法 ...
- Java编程的逻辑 (57) - 二进制文件和字节流
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- 【AtCoder】ARC089
C - Traveling 先看能不能走到,再看看奇偶性是否相同 #include <bits/stdc++.h> #define fi first #define se second # ...
- Codeforces 466E Information Graph
Information Graph 把询问离线之后就能随便搞了, 去check一下是不是祖先, 可以用倍增也能用dfs序. #include<bits/stdc++.h> #define ...
- 007.Zabbix监控图形绘制
一 Graphs配置 1.1 新建图形 Graphs是将数据展示为图像,以视觉化形式展示,Graphs的配置保存在主机和模板中. Configuration---->Hosts---->G ...
- i春秋CTF web题(1)
之前边看writeup,边做实验吧的web题,多多少少有些收获.但是知识点都已记不清.所以这次借助i春秋这个平台边做题,就当记笔记一样写写writeup(其实都大部分还是借鉴其他人的writeup). ...