鱼鱼Chen之学写自己的apk(七) 数据库的实际运用

五一放了个假,休息了几天、、、、

这次主要是运用数据库,Android内嵌有SQLite,这是一款轻量级的数据库,具体的可以百度。效果呢,主要是通过一些点击事件实现数据的插入,查找,修改,删除,最后通过一个listview表现出来。效果如下(因为是动态的,图示仅供参考,可以下载放在最后的源码自己跑跑看)


关于实现的功能如下:1、完成3个填选框后后,点击提交可以插入数据。并自动刷新listview,所有数据均由数据库提供。2、点击列表项,弹出对话框,可以选择删除,会从数据库中删除。可以选择修改,此时按钮自动文字编程修正,修改完成后数据会更新。

关于此篇中出现的关于ListView的用法,不多做解释,参考上一篇

鱼鱼Chen之学写自己的apk(六)ListView带动画图标

http://blog.csdn.net/zerolovesc1993/article/details/45334699

同理,关于Handler   Message的用法,参考

鱼鱼Chen之学写自己的apk(五)使用Handler完成Android里的多线程操作实例

http://blog.csdn.net/zerolovesc1993/article/details/45270153


下面正式开始:

一、分析一下结构


ListViewItem是我自定义的列表项类,MyListViewAdapter是我自定义的listview适配器。MySqliteHelper是自定义的sqlite生成器。布局的话,老样子,分别对应主布局和listview的布局


二、先配置好listview

布局文件xml,很简单,3个textview,稍微拍一下版就好了

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/list_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:textSize="30sp" />

    <TextView
        android:id="@+id/list_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/list_name"
        android:layout_marginTop="16dp"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/list_class"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_marginTop="20dp"
        android:textSize="25sp" />

</RelativeLayout>
接着,是listviewadapter的代码,这些就不解释了,参考之前的就好。直接上代码

package com.dota.example.fishychenofsqlite;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class MyListViewAdapter extends ArrayAdapter<ListViewItem> {
	private Context context;
	private int resourceId;
	private ListViewItem item;
	private ViewHolder holder;

	public MyListViewAdapter(Context context, int resource,
			List<ListViewItem> objects) {
		super(context, resource, objects);
		this.context = context;
		this.resourceId = resource;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		View view;
		item = getItem(position);
		if (convertView == null) {
			view = LayoutInflater.from(context).inflate(resourceId, parent,
					false);
			holder = new ViewHolder();
			holder.textName = (TextView) view.findViewById(R.id.list_name);
			holder.textNumber = (TextView) view.findViewById(R.id.list_number);
			holder.textClass = (TextView) view.findViewById(R.id.list_class);
			view.setTag(holder);
		} else {
			view = convertView;
			holder = (ViewHolder) view.getTag();
		}
		holder.textName.setText(item.getName());
		holder.textClass.setText(item.getClasses());
		holder.textNumber.setText(item.getNumber());
		return view;
	}
}

class ViewHolder {
	TextView textName, textNumber, textClass;
}

接着是自定义的listview的item项

public class ListViewItem {
	private String name, classes, number;

	public ListViewItem(String name, String classes, String number) {
		this.name = name;
		this.classes = classes;
		this.number = number;
	}

	public String getName() {
		return name;
	}

	public String getClasses() {
		return classes;
	}

	public String getNumber() {
		return number;
	}
	
}
三、创建自定义的sqlite打开帮助器

还是先上代码,再做解释

public class MySqliteHelper extends SQLiteOpenHelper {
	private Context context;
	private static final String CREATE_TABLE = "create table MyTable("
			+ "id integer primary key autoincrement, " + "name text unique, "
			+ "class text, " + "number text)";

	public MySqliteHelper(Context context, String name, CursorFactory factory,
			int version) {
		super(context, name, factory, version);
		this.context = context;
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_TABLE);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// TODO Auto-generated method stub

	}

}
首先我们让自定义类继承SQLiteOpenHelper,实现2个抽象方法。并实现构造方法,4个参数,分别代表上下文、名称(db格式)、指针工厂(null就行,指向数据库某一行,一般用不到)、版本号

结合着主活动中的实例化,我们看一下用法

dbHelper = new MySqliteHelper(this, "Table.db", null, 1);
当Table.db不存在时,便会调用onCreate中的代码,存在便无影响。除非version的int比之前大,比如是2。那么此时会调用onUpgrade方法。db.execSQL即可生成某个表格

关于创建表格的格式几个注意点:栏名   格式   约束条件(可选),其中格式有integer(整形),text(文本),real(浮点型),blob(数据块)。 primary  key指唯一键,autoincrement指自增长。而unique关键字指唯一,即不能重复插入无效。还有一个要注意的是,输入某一栏后记得加空格,新手容易犯这个错误,否则会报错,因为你输入的sql语句是有问题的。

关于创建,主要在主活动中oncreate方法里写入,就可以了

dbHelper = new MySqliteHelper(this, "Table.db", null, 1);


四、查找数据

private void initData() {
		items.clear();
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		Cursor cursor = db.query("MyTable", null, null, null, null, null, null);
		if (cursor.moveToFirst()) {
			do {
				String name = cursor.getString(cursor.getColumnIndex("name"));
				String classes = cursor.getString(cursor
						.getColumnIndex("class"));
				String number = cursor.getString(cursor
						.getColumnIndex("number"));
				items.add(new ListViewItem(name, classes, number));
			} while (cursor.moveToNext());
		}
	}
先通过我们自定义的类的实力对象,使用getWriteableDatabase方法,得到sqlitedatabase实例对象。(其实这边用getReadableDatabase可能会更好,该方法会调用getWriteableDatabase)。然后用Cursor类的实例对象实现db.query方法。7个参数,第一个是表格名,第二个是栏名,第三个和第四个连起来是一个完整的约束条件。比如

"name = ?"(第三个), new String[] { editName.getText().toString() }(第四个)。后三个一般用不到,也是3个约束条件,具体用法可以百度sqlite语法。这边我只要表内的所有数据。记得,一定要加

if (cursor.moveToFirst())
这个判断,不然会报错。表明cursor能指向第一项。循环内的还是比较好理解的,通过的cursor的getxxx方法(xxx代表数据类型),然后得到对应的栏名。最后将其加入自定义的列表项集合里。

这边,要用到多线程操作。因为遍历数据库,以及配置适配器都算是耗时操作。

class NewThread extends Thread implements Runnable {
		@Override
		public void run() {
			super.run();
			synchronized (MainActivity.class) {
				try {
					initData();
					itemAdapter = new MyListViewAdapter(MainActivity.this,
							R.layout.listview_layout, items);
					Message message = new Message();
					message.what = UPDATA_LISTVIEW;
					mHandler.sendMessage(message);
				} catch (Exception e) {
					// TODO: handle exception
				}
			}
		}
	}
handler中的代码

mHandler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				switch (msg.what) {
				case UPDATA_LISTVIEW:
					listView.setAdapter(itemAdapter);
					break;

				default:
					break;
				}
			}
		};
这次为了方便,我直接用了匿名类。

定义

private static final int UPDATA_LISTVIEW = 1;


四、实现数据的插入

事件我是写在按钮里的

SQLiteDatabase db = dbHelper.getWritableDatabase();
			ContentValues values = new ContentValues();
			values.put("name", editName.getText().toString());
			values.put("class", spinner.getSelectedItem().toString());
			values.put("number", editNumber.getText().toString());
			try {
				db.insert("MyTable", null, values);
				Toast.makeText(MainActivity.this, "插入成功", Toast.LENGTH_SHORT)
						.show();
				mThread = new NewThread();
				mThread.start();
			} catch (Exception e) {
				// TODO: handle exception
			}
第一步是一样的,得到db这个实例对象。并创建一个ContentValues类的实例对象。通过put方法,填入值,记得key对应栏名。最后调用insert方法就行了,这边3个参数,分别是表名、 nullColumnHack、值。第二个参数是干啥的呢? 当values参数为空或者里面没有内容的时候,我们insert是会失败的(底层数据库不允许插入一个空行),为了防止这种情况,我们要在这里指定一个 列名,到时候如果发现将要插入的行为空行时,就会将你指定的这个列名的值设为null,然后再向数据库中插入。当然了,这边我们直接用null就行,因为我们value的值是不可能为空的(第二个数据我用的spinner)。实际过程中,填入数据的时候,加一个适当的判断就可以了。


五、实现数据的更新

SQLiteDatabase db = dbHelper.getWritableDatabase();
			ContentValues values = new ContentValues();
			values.put("name", editName.getText().toString());
			values.put("class", spinner.getSelectedItem().toString());
			values.put("number", editNumber.getText().toString());
			db.update("MyTable", values, "name = ?", new String[] { editName
					.getText().toString() });
这边和插入差不多,只不过updata是4个参数,分别是表名、值、约束条件(2个参数),这种写法之前在查找部分已经说过了。


六、实现数据的删除

SQLiteDatabase db = dbHelper
										.getWritableDatabase();
								db.delete("MyTable", "name = ?",
										new String[] { items.get(position)
												.getName() });
这边的话,和更新的格式是差不多的,delete方法是3个参数,表名、约束条件组。


接下来是完整的主活动的代码

public class MainActivity extends Activity implements OnFocusChangeListener,
		OnClickListener {
	private EditText editName, editNumber;
	private Spinner spinner;
	private ListView listView;
	private List<ListViewItem> items;
	private ArrayAdapter<CharSequence> adapter;
	private MyListViewAdapter itemAdapter;
	private Button btnSubmit;
	private MySqliteHelper dbHelper;
	public Handler mHandler;
	private Thread mThread;
	private boolean flag = true;
	private static final int UPDATA_LISTVIEW = 1;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		init();
		mHandler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				switch (msg.what) {
				case UPDATA_LISTVIEW:
					listView.setAdapter(itemAdapter);
					break;

				default:
					break;
				}
			}
		};
		listView.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					final int position, long id) {
				AlertDialog.Builder dialog = new AlertDialog.Builder(
						MainActivity.this);
				dialog.setTitle("核对");
				dialog.setMessage("确定要删除吗?");
				dialog.setPositiveButton("确认",
						new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog,
									int which) {
								SQLiteDatabase db = dbHelper
										.getWritableDatabase();
								db.delete("MyTable", "name = ?",
										new String[] { items.get(position)
												.getName() });
								items.remove(position);
								mThread = new NewThread();
								mThread.start();
							}
						});
				dialog.setNegativeButton("修正",
						new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog,
									int which) {
								editName.setText(items.get(position).getName());
								editNumber.setText(items.get(position)
										.getNumber());
								flag = false;
								btnSubmit.setText("修正");
							}
						});
				dialog.show();
			}
		});
		mThread = new NewThread();
		mThread.start();
	}

	private void init() {
		CharSequence[] charSequences = getResources().getStringArray(
				R.array.spinner_item_name);
		adapter = new ArrayAdapter<CharSequence>(this,
				android.R.layout.simple_spinner_item, charSequences);
		dbHelper = new MySqliteHelper(this, "Table.db", null, 1);
		editName = (EditText) findViewById(R.id.editName);
		editNumber = (EditText) findViewById(R.id.editNumber);
		spinner = (Spinner) findViewById(R.id.spinner);
		spinner.setAdapter(adapter);
		listView = (ListView) findViewById(R.id.listView);
		items = new ArrayList<ListViewItem>();
		btnSubmit = (Button) findViewById(R.id.btnSubmit);
		editName.setOnFocusChangeListener(this);
		editNumber.setOnFocusChangeListener(this);
		btnSubmit.setOnClickListener(this);
		initData();
	}

	private void initData() {
		items.clear();
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		Cursor cursor = db.query("MyTable", null, null, null, null, null, null);
		if (cursor.moveToFirst()) {
			do {
				String name = cursor.getString(cursor.getColumnIndex("name"));
				String classes = cursor.getString(cursor
						.getColumnIndex("class"));
				String number = cursor.getString(cursor
						.getColumnIndex("number"));
				items.add(new ListViewItem(name, classes, number));
			} while (cursor.moveToNext());
		}
	}

	@Override
	public void onFocusChange(View v, boolean hasFocus) {
		((EditText) v).setHint("");
		switch (v.getId()) {
		case R.id.editName:
			if ((editName.getText().toString().equals("")) && !hasFocus) {
				editName.setHint("请输入姓名");
			}
			break;
		case R.id.editNumber:
			if ((editNumber.getText().toString().equals("")) && !hasFocus) {
				editNumber.setHint("请输入学号");
			}
			break;
		default:
			break;
		}
	}

	@Override
	public void onClick(View v) {
		if (flag) {
			SQLiteDatabase db = dbHelper.getWritableDatabase();
			ContentValues values = new ContentValues();
			values.put("name", editName.getText().toString());
			values.put("class", spinner.getSelectedItem().toString());
			values.put("number", editNumber.getText().toString());
			try {
				db.insert("MyTable", null, values);
				Toast.makeText(MainActivity.this, "插入成功", Toast.LENGTH_SHORT)
						.show();
				mThread = new NewThread();
				mThread.start();
			} catch (Exception e) {
				// TODO: handle exception
			}
		} else {
			SQLiteDatabase db = dbHelper.getWritableDatabase();
			ContentValues values = new ContentValues();
			values.put("name", editName.getText().toString());
			values.put("class", spinner.getSelectedItem().toString());
			values.put("number", editNumber.getText().toString());
			db.update("MyTable", values, "name = ?", new String[] { editName
					.getText().toString() });
			btnSubmit.setText("提交");
			flag = true;
			mThread = new NewThread();
			mThread.start();
		}
	}

	class NewThread extends Thread implements Runnable {
		@Override
		public void run() {
			super.run();
			synchronized (MainActivity.class) {
				try {
					initData();
					itemAdapter = new MyListViewAdapter(MainActivity.this,
							R.layout.listview_layout, items);
					Message message = new Message();
					message.what = UPDATA_LISTVIEW;
					mHandler.sendMessage(message);
				} catch (Exception e) {
					// TODO: handle exception
				}
			}
		}
	}
}
主布局xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:focusableInTouchMode="true"
    tools:context="com.dota.example.fishychenofsqlite.MainActivity" >

    <RelativeLayout
        android:id="@+id/relativeLayoutTop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:padding="8dp" >

        <TextView
            android:id="@+id/textName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="姓名"
            android:textSize="25sp" />

        <EditText
            android:id="@+id/editName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@+id/textName"
            android:hint="请输入姓名"
            android:lines="1"
            android:maxLines="1" />

        <TextView
            android:id="@+id/textClass"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/textName"
            android:layout_marginTop="16dp"
            android:text="班级"
            android:textSize="25sp" />

        <Spinner
            android:id="@+id/spinner"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/textClass"
            android:layout_below="@+id/editName"
            android:layout_toRightOf="@+id/textClass" />

        <TextView
            android:id="@+id/textNumber"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/textClass"
            android:layout_marginTop="16dp"
            android:text="学号"
            android:textSize="25sp" />

        <EditText
            android:id="@+id/editNumber"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/textNumber"
            android:layout_toRightOf="@+id/textNumber"
            android:hint="请输入学号"
            android:inputType="number" />

        <Button
            android:id="@+id/btnSubmit"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/editNumber"
            android:text="提交"
            android:textSize="20sp" />
    </RelativeLayout>

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/relativeLayoutTop" >
    </ListView>

</RelativeLayout>
最后是完整的代码

百度云链接:http://pan.baidu.com/s/1pJKDUkF














  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值