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(); } }; }