2014-10-31Android学习------SQLite数据库操作(四)-----数据库模块(二)增删改查实例展示

2022-03-07 13:36:29 浏览数 (1)

我学习Android都是结合源代码去学习,这样比较直观,非常清楚的看清效果,觉得很好,今天的学习源码是网上找的个db 源码 百度搜就知道很多下载的地方 我写的东西有可能比较乱,如果单一的篇章没看明白,请看上一篇文章

上篇文章 地址:http://blog.csdn.net/u014737138/article/details/40620627

android操作数据库实例 源码 百度下应该可以搜到,这里我也上传一份到csdn 上,地址:http://download.csdn.net/detail/u014737138/8107809

接下来就不废话了,看看代码把:主要是两个类 一个是数据库类,一个是activity类

一.数据库类

代码语言:javascript复制
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class SQLHelper extends SQLiteOpenHelper {
	
	private final static String DATABASE_NAME = "todo_db";//数据库名
	private final static int DATABASE_VERSION = 1;//数据库版本号
	private final static String TABLE_NAME = "todo_table";//数据库表名
	public final static String FIELD_id = "_id";//
	public final static String FIELD_TEXT = "todo_text";//字段

	public SQLHelper(Context context) {
		super(context, DATABASE_NAME, null, DATABASE_VERSION);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		// TODO Auto-generated method stub
		String sql = "CREATE TABLE "   TABLE_NAME   " ("   FIELD_id
				  " INTEGER primary key autoincrement, "   " "   FIELD_TEXT
				  " text)";
		db.execSQL(sql);

	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// TODO Auto-generated method stub
		String sql = "DROP TABLE IF EXISTS "   TABLE_NAME;
		db.execSQL(sql);
		onCreate(db);
	}	
	
	
	public Cursor select() {
		SQLiteDatabase db = this.getReadableDatabase();
		Cursor cursor = db
				.query(TABLE_NAME, null, null, null, null, null, null);
		return cursor;
	}

	public long insert(String text) {
		SQLiteDatabase db = this.getWritableDatabase();
		ContentValues cv = new ContentValues();
		cv.put(FIELD_TEXT, text);
		long row = db.insert(TABLE_NAME, null, cv);
		return row;
	}

	public void delete(int id) {
		SQLiteDatabase db = this.getWritableDatabase();
		String where = FIELD_id   " = ?";
		String[] whereValue = { Integer.toString(id) };
		db.delete(TABLE_NAME, where, whereValue);
	}

	public void update(int id, String text) {
		SQLiteDatabase db = this.getWritableDatabase();
		String where = FIELD_id   " = ?";
		String[] whereValue = { Integer.toString(id) };
		ContentValues cv = new ContentValues();
		cv.put(FIELD_TEXT, text);
		db.update(TABLE_NAME, cv, where, whereValue);
	}

}

二.activity展示类

代码语言:javascript复制
import com.wust.dbtest.R;

import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteCursor;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;


public class DBActivity extends Activity {

	private SQLHelper mySQLHelper;
	private Cursor myCursor;
	private ListView myListView;
	private EditText myEditText;
	private int _id;
	protected final static int MENU_ADD = Menu.FIRST;
	protected final static int MENU_EDIT = Menu.FIRST   1;
	protected final static int MENU_DELETE = Menu.FIRST   2;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		// 找到main.xml里面的控件
	    myListView = (ListView) this.findViewById(R.id.myListView);
	    myEditText = (EditText) this.findViewById(R.id.myEditText);
	    //连接数据库
	    mySQLHelper = new SQLHelper(this);
	    //取得数据库里面的内容
	    myCursor = mySQLHelper.select();
	    
	    //为ListView做数据处理
	    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.list, myCursor, new String[]{ SQLHelper.FIELD_TEXT }, new int[]{ R.id.listTextView1 });
	    myListView.setAdapter(adapter);
	    myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> arg0, View view, int position,
					long id) {
				// TODO Auto-generated method stub
		        /* 将myCursor移到所点击的值 */
		        myCursor.moveToPosition(position);
		        /* 取得字段_id的值 */
		        _id = myCursor.getInt(0);
		        /* 取得字段todo_text的值 */
		        myEditText.setText(myCursor.getString(1));
			}
		});
	    
	    myListView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

			@Override
			public void onItemSelected(AdapterView<?> arg0, View view,
					int position, long id) {
				// TODO Auto-generated method stub
		        /* getSelectedItem所取得的是SQLiteCursor */
		        SQLiteCursor sc = (SQLiteCursor) arg0.getSelectedItem();
		        _id = sc.getInt(0);
		        myEditText.setText(sc.getString(1));
			}

			@Override
			public void onNothingSelected(AdapterView<?> view) {
				// TODO Auto-generated method stub
				
			}
		});
	}

	//由当前的activity负责执行创建OptionMenu模式的菜单
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		super.onCreateOptionsMenu(menu);
	    menu.add(Menu.NONE, MENU_ADD, 0, R.string.strAddButton);
	    menu.add(Menu.NONE, MENU_EDIT, 0, R.string.strEditButton);
	    menu.add(Menu.NONE, MENU_DELETE, 0, R.string.strDeleteButton);

	    return true;
	}

	//菜单被选中的响应事件  参数是选中的那个菜单item
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
	    super.onOptionsItemSelected(item);
	    switch (item.getItemId())
	    {
	      case MENU_ADD:
	        this.addTodo();
	        break;
	      case MENU_EDIT:
	        this.editTodo();
	        break;
	      case MENU_DELETE:
	        this.deleteTodo();
	        break;
	    }
	    return true;
	}

	private void deleteTodo() {
		// TODO Auto-generated method stub
		if (_id == 0)
			return;
		/* 删除数据 */
		mySQLHelper.delete(_id);
		myCursor.requery();
		myListView.invalidateViews();// 刷新视图
		myEditText.setText("");
		_id = 0;
	}

	private void editTodo() {
		// TODO Auto-generated method stub
		if (myEditText.getText().toString().equals(""))
			return;
		/* 修改数据 */
		mySQLHelper.update(_id, myEditText.getText().toString());
		myCursor.requery();
		myListView.invalidateViews();// 刷新视图
		myEditText.setText("");
		_id = 0;
	}

	private void addTodo() {
		// TODO Auto-generated method stub
		if (myEditText.getText().toString().equals(""))
			return;
		/* 添加数据到数据库 */
		mySQLHelper.insert(myEditText.getText().toString());
		/* 重新查询 */
		myCursor.requery();
		/* 重新整理myListView */
		myListView.invalidateViews();// 刷新视图
		myEditText.setText("");
		_id = 0;
	}
	
	
	
	

}

三.main.xml文件

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/white"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello"
        android:textColor="@drawable/black" />

    <EditText
        android:id="@ id/myEditText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textColor="@drawable/black" >
        </EditText>

    <ListView
        android:id="@ id/myListView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/red" >
    </ListView>

</LinearLayout>

东西就这么点 很简单的就实现了增删改查

下面先看看效果吧

接下来我们回顾下这个里面我们需要掌握什么样的知识:

1.首先是数据库

让我们自定义的SQLHelper 继承 SQLiteOpenHelper 那边必须实现三个函数:

1).构造函数:public SQLHelper(Context context) Eclipse显示的构造函数有四个参数,分别代表是:上下午,数据库名字,游标工厂,版本号

具体的请参看我前面的文章http://blog.csdn.net/u014737138/article/details/40623915

2).重载创建数据库函数 public void onCreate(SQLiteDatabase db)

3). 重载版本更新函数:public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 在当数据库版本更新的时候执行这个函数,首先需要让当前的数据库销毁掉,然后再调用上面的onCreate函数就可以

4).就下来就是写自己的表操作函数,增删改查

2.展示界面的实现

1).这里也是自定义了一个ListView控件,那么我需要给配置一个适配器 源码中给出的这个SimpleCursorAdapter

首先看下API中的定义

Public Constructors

public SimpleCursorAdapter (Context context, int layout, Cursor c, String[] from, int[] to)

Since: API Level 1

This constructor is deprecated. This option is discouraged, as it results in Cursor queries being performed on the application's UI thread and thus can cause poor responsiveness or even Application Not Responding errors. As an alternative, use LoaderManager with a CursorLoader.

Constructor the enables auto-requery.

此构造已被弃用。 此项构造函数不提倡的,因为它会导致应用程序的UI线程正在执行游标的查询,从而可能会导致反应不佳,甚至应用程序无响应的错误。 作为替代,可以使用LoaderManager用CursorLoader

这里说应用程序的UI线程可能会导致异常,应该是当数据量过大的时候,查询时间需要很久,超过6秒,那么就会出现anr异常把,我猜是这种,目前学的不够深,有错的话就放在评论里面

但是对于这个测试程序而言还是可以用的、

public SimpleCursorAdapter (Context context, int layout, Cursor c, String[] from, int[] to, int flags)

Since: API Level 11

Standard constructor.

Parameters

context

The context where the ListView associated with this SimpleListItemFactory is running

layout

resource identifier of a layout file that defines the views for this list item. The layout file should include at least those named views defined in "to"

c

The database cursor. Can be null if the cursor is not available yet.

from

A list of column names representing the data to bind to the UI. Can be null if the cursor is not available yet.

to

The views that should display column in the "from" parameter. These should all be TextViews. The first N views in this list are given the values of the first N columns in the from parameter. Can be null if the cursor is not available yet.

flags

Flags used to determine the behavior of the adapter, as per CursorAdapter(Context, Cursor, int).

标准的构造函数。 参数 上下文:ListView对于的activity的上下文 布局:布局文件的id。布局文件中应包括“to”定义的那些控件id c:数据库游标。 from:表中的数据列名的列表绑定到用户界面。意思就是把游标中那个列的数据绑定到界面中去 to:这些都应该是TextViews。意思就是将游标中的数据显示在布局文件中哪些控件上,这个参数是控件的id号 flags:用于确定适配器的行为 其实这里我们也可以用前面讲到的SimpleAdapter去实现它,那就是参数不是游标数据 Cursor ,而是

public SimpleAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)

我们只需要利用Cursor构造出我们需要的data不就可以了么

我们把Cursor中的每一行定义为一个object 其实他表示的就是一个表的数据,这个表有多个字段,那么它不就是一个实体类么,我们只需要取出这个实体类的某个字段作为object不就行了

Map<String,object>,这个String是表示键值 这里写的肯定就是在布局文件中的id的名称了,因为它必须跟后面的String[]相匹配的

然后再将map放入list里面不就行了,就成为data了么

参看前面的文章:http://blog.csdn.net/u014737138/article/details/40481965

这个构造函数先就说这么多吧 时间有限 我们继续:

2).设置适配器

上面我们把适配器构造出来,接下来就是让ListView控件是匹配它

只有一行代码

myListView.setAdapter(adapter);

3).设定相应函数

当我们让ListView有了数据之后,我们就需要实现它的每个item的点击触摸响应事件了,这个事件有两种:一种是点击,一种是选中

A. myListView.setOnItemClickListener(new AdapterView.OnItemClickListener()

B. myListView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()

4).视图的更新

其实做完上面的那些我们的ListView控件基本完成了实现,但是还有一个没有处理,就是视图的更新

在前面的一篇文章就讲到了视图的更新 主要是两个函数:invalidate 和postInvalidate

参看前面的文章 地址:http://blog.csdn.net/u014737138/article/details/40620627

但是这个程序里面我们又可以看见一个函数:

myListView.invalidateViews();// 刷新视图

这是直接UI线程去执行的,这个函数就是重建视图并且重画

我们来看看它的定义:

void

invalidateViews() Causes all the views to be rebuilt and redrawn.

3 .requery()函数:

myCursor.requery();//这里用到了一个游标数据的重新查询 这也是一个非常危险的操作 ,API中也说了这个是一个被废弃方法

abstract boolean

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 cursor comes back

这个解释中还告诉你了解决方案

它说不要使用这个方法,你只需要申请一个新的游标,当这个新的游标值返回来的时候(当你定义的新的游标有值的时候),你就能够在异步更新视图列表中做到这一点(让数据库中最新的数据显示在列表中)

下面我们要思考为什么重复查询很危险,不推荐使用呢,我想更上面的那个构造SimpleCursorAdapter是一个意思,当我们的数据量非常大的时候,这个操作需要更多的时间,时间一长,我们的UI进程不能等你的啊!好像听说只有6秒,具体多少我也不清楚,超过这个时间,程序肯定蹦了,出现anr异常 这就是为什么如果一个业务的处理需要花费很多时间的时候,我们需要服务或者新开一个进程去让执行,等他们执行完了告诉主线程,你更新吧,我已经做完了。

4.菜单的处理

这一节放在下篇文章中再介绍吧 请查看我的下一篇文章 菜单的处理(一) OptionsMenu

0 人点赞