在实际开发中,往往避免不了在界面上操作数据库。例如,开发一个购物车,需要将购物车中的商品以列表的形式展示,并且还需要对购物车中的商品进行增删改查操作。要实现这些功能就需要使用ListView和SQLite数据库。接下来通过一个 “商品展示“案例来实现在界面上操作数据库。
listview与adapterde用法参考地址:http://www.cnblogs.com/zhengbeibei/archive/2013/05/14/3078805.html
SQLite数据库的使用参考地址:http://blog.csdn.net/xushuaic/article/details/8170614
1.创建程序
首先创建一个名为“商品展示”的应用程序。添加3个TextView,分别用于显示数据库中的某条数据的id,商品名称,金额。三个ImageView用于增加金额,减少金额,删除数据。设计用户交互界面如图:
该图对应的布局文件(activity_main.xml)如下所示:
<?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"
android:background="#f5f5dc">
<LinearLayout
android:id="@+id/LL"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="商品名称"
android:id="@+id/name"/>
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="金额"
android:id="@+id/price"/>
<ImageView
android:id="@+id/addAccount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/ic_input_add"/>
</LinearLayout>
<LinearLayout
android:id="@+id/LL2"
android:layout_below="@id/LL"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="3dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="编号"
android:textSize="20dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="商品名称"
android:textSize="20dp"
android:layout_marginLeft="15dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="价格"
android:textSize="20dp"
android:layout_marginLeft="50dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="操作"
android:textSize="20dp"
android:layout_marginLeft="80dp"/>
</LinearLayout>
<ListView
android:id="@+id/display"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fadeScrollbars="false"
android:divider="#FFFFFF"
android:dividerHeight="2dp"
android:layout_below="@+id/LL2" />
</RelativeLayout>
2.创建ListView Item布局
在res/layout目录下创建一个item.xml文件,编写成如图所示的界面:
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_margin="10dp">
<TextView
android:id="@+id/idTV"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="1"
android:textColor="#000000"
android:textSize="20sp"
/>
<TextView
android:id="@+id/nameTV"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="Towel"
android:textColor="#000000"
android:textSize="20sp"
/>
<TextView
android:id="@+id/priceTV"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="100"
android:textColor="#000000"
android:textSize="20sp"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="5dp">
<ImageView
android:id="@+id/up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/arrow_up_float"/>
<ImageView
android:id="@+id/down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/arrow_down_float"/>
</LinearLayout>
<ImageView
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/ic_menu_delete"/>
</LinearLayout>
3.创建数据库
创建数据库属于数据操作,因此创建一个名为model的包,
并在该包中定义一个类继承自SQLiteOpenHelper,代码如下:
package bzu.edu.cn.filedemo.model;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
/**
* Created by yn on 2017/4/17.
*/
public class AccountDB extends SQLiteOpenHelper{
public Context context;
public static final String DB_NAME="Account.db";
public static final String ACCOUNT="create table account(id integer primary key autoincrement,name text,balance integer)";
public AccountDB(Context context) {
super(context, DB_NAME, null, 1);
this.context=context;
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.d("AccountDB","数据库创建成功");
db.execSQL(ACCOUNT);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
4.创建Account类
在操作数据库时将数据存放至一个JavaBean对象中操作起来会比较方便。
因此在model包下定义一个类Account,代码如下:
package bzu.edu.cn.filedemo.model;
/**
* Created by yn on 2017/4/17.
*/
public class Account {
private long id;
private String name;
private Integer balance;
public Account() {}
public Account(String name, Integer balance) {
this.name = name;
this.balance = balance;
}
public Account(long id, String name, Integer balance) {
this.id = id;
this.name = name;
this.balance = balance;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getBalance() {
return balance;
}
public void setBalance(Integer balance) {
this.balance = balance;
}
@Override
public String toString() {
return
"[编号:" + id +
", 商品名称:" + name +
", 价格:" + balance +
"]";
}
}
5.创建数据操作逻辑类
在model包下创建一个AccountDao类用于操作数据,来实现数据库的增、删、改、查。代码如下:
package bzu.edu.cn.filedemo.model;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
import java.util.List;
/**
* Created by yn on 2017/4/17.
*/
public class AccountDao {
private AccountDB accountDB;
public AccountDao(Context context){
accountDB=new AccountDB(context);
}
//插入数据
public void insert(Account account){
//获取数据库对象
SQLiteDatabase sqLiteDatabase=accountDB.getWritableDatabase();
ContentValues values=new ContentValues(); //用来装载要插入的数据的Map
values.put("name",account.getName());
values.put("balance",account.getBalance());
long id=sqLiteDatabase.insert("account",null,values);
account.setId(id);
}
//查询所有数据
public List<Account> querryAll(){
SQLiteDatabase sqLiteDatabase=accountDB.getReadableDatabase();
Cursor cursor=sqLiteDatabase.query("account",null,null,null,null,null,null);
List<Account> list=new ArrayList<Account>();
if(cursor.moveToFirst()) {
do{
long id=cursor.getLong(cursor.getColumnIndex("id"));
String name=cursor.getString(1);
int balance=cursor.getInt(2);
list.add(new Account(id,name,balance));
}while(cursor.moveToNext());
}
return list;
}
//修改数据
public int update(Account account){
SQLiteDatabase sqLiteDatabase=accountDB.getWritableDatabase();
ContentValues values=new ContentValues();
values.put("name",account.getName());
values.put("balance",account.getBalance());
int count=sqLiteDatabase.update("account",values,"id=?",new String[]{account.getId()+""});
return count;
}
//根据id删除数据
public int delete(long id){
SQLiteDatabase sqLiteDatabase=accountDB.getWritableDatabase();
int count=sqLiteDatabase.delete("account","id=?",new String[]{id+""});
return count;
}
}
6.编写界面交互代码(MainActivity)
用于实现将数据库中的数据以ListView的形式展示在界面上,需要对ListView进行数据适配,
如果不对LIstView进行数据适配,那么就无法在界面上看到布局文件创建的ListView。
在程序中使用了对话框,当点击删除图标时弹出一个对话框。还对ListView中每一行设置了点击事件。
具体代码如下所示:
package bzu.edu.cn.filedemo;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import bzu.edu.cn.filedemo.model.Account;
import bzu.edu.cn.filedemo.model.AccountDao;
public class Main4Activity extends AppCompatActivity {
private TextView name, account;
private ImageView iv;
private ListView lv;
AccountArray accountArray;
private List<Account> accountList;
//private AccountDB accountDB;
private AccountDao dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main4);
//找到我们需要的控件
name = (TextView) findViewById(R.id.name);
account = (TextView) findViewById(R.id.price);
iv = (ImageView) findViewById(R.id.addAccount);
lv = (ListView) findViewById(R.id.display);
//添加监听事件,监听条目点击事件
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//获取点击位置上的数据
Account account=(Account)parent.getItemAtPosition(position);
Toast.makeText(Main4Activity.this,account.toString(),Toast.LENGTH_LONG).show();
}
});
//实例化AccountDao
dao = new AccountDao(this);
//调用方法查询出所有数据
selectAccount();
//ImageView 的点击事件
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addAccount();
selectAccount();
}
});
}
//增加一条数据
private void addAccount() {
String name1 = name.getText().toString();
String price = account.getText().toString();
accountList = new ArrayList<>();
//检验商品名称和价格是否为空
if(name1.equals("")&&price.equals("")){
Toast.makeText(this,"请输入商品名称和价格",Toast.LENGTH_LONG).show();
}
else {
//如果balance不是空字符串,则进行类型转化
Account a = new Account(name1, price.equals("") ? 0 : Integer.parseInt(price));
dao.insert(a); //插入数据库
accountList.add(a); //插入集合
}
name.setText("");
account.setText("");
}
//查询数据并显示在ListView上
private void selectAccount() {
accountList = dao.querryAll(); //从数据库查询出所有数据
//给ListView添加适配器
accountArray = new AccountArray(Main4Activity.this, R.layout.shop_item, accountList);
lv.setAdapter(accountArray);
}
//自定义一个适配器
public class AccountArray extends ArrayAdapter<Account> {
//private TextView id,name,price;
private int resourseId;
private Context context;
// private AccountDao dao;
//List<Account> list;
public AccountArray(Context context, int resource, List<Account> list) {
super(context, resource, list);
resourseId=resource;
//this.list=list;
this.context=context;
}
@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//根据当前位置获得Account对象
final Account account=getItem(position);
View view;
ViewHolder viewHolder;
//ListView的优化
if(convertView==null){
view= LayoutInflater.from(getContext()).inflate(resourseId,parent,false);
viewHolder=new ViewHolder();
viewHolder.id=(TextView)view.findViewById(R.id.idTV);
viewHolder.name=(TextView)view.findViewById(R.id.nameTV);
viewHolder.price=(TextView)view.findViewById(R.id.priceTV);
view.setTag(viewHolder); //把viewHolder存储到view中
}else{
view=convertView;
viewHolder=(ViewHolder)view.getTag(); //重新获取viewHolder
}
viewHolder.id.setText(account.getId()+"");
viewHolder.name.setText(account.getName());
viewHolder.price.setText(account.getBalance()+"");
//获取控件
ImageView up=(ImageView)view.findViewById(R.id.up);
ImageView down=(ImageView)view.findViewById(R.id.down);
ImageView delete=(ImageView)view.findViewById(R.id.delete);
//向上箭头的点击事件
up.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
account.setBalance(account.getBalance() + 1); //修改值
dao.update(account); //更新数据库
notifyDataSetChanged(); //刷新界面
}
});
//下箭头的点击事件
down.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
account.setBalance(account.getBalance()-1);
dao.update(account);
notifyDataSetChanged();
}
});
//删除的点击事件
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//删除之前弹出一个对话框
android.content.DialogInterface.OnClickListener listener = new android.content.DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
accountList.remove(account);
dao.delete(account.getId());
notifyDataSetChanged();
}
};
//创建对话框
AlertDialog.Builder builder=new AlertDialog.Builder(context);
builder.setTitle("你确定要删除吗?"); //设置标题
builder.setPositiveButton("确定",listener); //设置确定按钮的文本以及监听器
builder.setNegativeButton("取消",null); //设置取消按钮
builder.show(); //显示对话框
}
});
return view;
}
class ViewHolder{
TextView id;
TextView name;
TextView price;
}
}
}
上述代码实现了界面管理数据库,(1)使用了ArrayAdapter适配器对ListView进行数据适配:
步骤:
自定义一个类继承ArrayAdapter;
对该类定义一个构造方法;
重写ArrayAdapter中的getView()方法;
调用getItem()方法,获取条目中的每一行
(2)对ListView进行优化:
复用ConvertView
重用ViewHolder
详细参考地址:http://www.tuicool.com/articles/uyiAZzA
http://blog.csdn.net/dfqin/article/details/7458853
代码如下:
(3)对ListView设置监听事件,点击每一行时获取此行的数据
(4)程序中使用了对话框AlertDialog。对话框的创建代码如下:
7.程序运行结果
1.程序首次运行结果:
2。添加商品
增加或减少商品金额
删除商品
点击每一行时