Android移动应用开发之数据存储


一、SQLite数据库简介

SQLite是遵循ACID的关系型数据库管理系统,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

二、数据库的创建

使用SQLiteOpenHelper的子类创建数据库,重写onCreate和onUpgrade即可:

ublic class MyHelper extends SQLiteOpenHelper {
    
    
    public MyHelper(Context context) {
    
    
        super(context, "test.db", null, 2);
    }
    //数据库第一次被创建时使用该方法
    @Override
    public void onCreate(SQLiteDatabase db) {
    
    
        //初始化数据库的表结构,执行一条建表的SQL语句
        db.execSQL("CREATE TABLE information(_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(20), price INTEGER)");
    }
    //当数据库的版本号增加时调用
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    
    
    }
}

三、数据库的使用

1、SQLite的基本操作

(1)增加一条数据

public void insert(String name, String price) {
    
    
    SQLiteDatabase db = helper.getWritableDatabase();   //获取可读写SQLiteDatabase对象
    ContentValues values = new ContentValues();     //创建ContentValues对象
    values.put("name", name);
    values.put("price", price);
    long id = db.insert("information", null, values);
    db.close();
}

(2)修改一条数据

public int update(String name, String price) {
    
    
    SQLiteDatabase db = helper.getWritableDatabase();
    ContentValues values = new ContentValues();
    values.put("price", price);
    int number = db.update("information", values, "name=?", new String[]{
    
    name});
    db.close();
    return number;
}

(3)删除一条数据

public int delete(long id) {
    
    
    SQLiteDatabase db = helper.getWritableDatabase();
    int number = db.delete("information", "_id=?", new String[]{
    
    id+""});
    db.close();
    return number;
}

(4)查询一条数据

public boolean find(long id) {
    
    
    SQLiteDatabase db = helper.getReadableDatabase();   //获取可读SQLiteDatabase对象
    Cursor cursor = db.query("information", null, "_id=?", new String[]{
    
    id+""}, null, null,null);
    boolean result = cursor.moveToNext();
    cursor.close();     //关闭游标
    db.close();
    return result;
}

除此之外还可以用execSQL和rawQuery进行查询,但execSQL没有返回值而rawQuery有:

//增加一条数据
db.execSQL("insert into information (name, price) values (?, ?)", new Object[]{
    
    name, price});
//修改一条数据
db.execSQL("update information set name=? where price=?", new Object[]{
    
    name, price});
//删除一条数据
db.execSQL("delete from information where _id=1");
//执行查询的SQL语句
Cursor cursor = db.rawQuery("select * from person where name=?", new String[]{
    
    name});

2、SQLite中的事务

PersonSQLiteOpenHelper helper = new PersonSQLiteOpenHelper(this);
SQLiteDatabase db = helper.getWritableDatabase();
//开始数据库事务
db.beginTransaction();
try {
    
    
    //执行转出操作
    db.execSQL("update person set account=account-1000 where name=?", new Object[]{
    
    "zhangsan"});
    //执行转入操作
    db.execSQL("update person set account=account+1000 where name=?", new Object[]{
    
    "lisi"});
    //标记数据库事务执行成功
    db.setTransactionSuccessful();
}catch (Exception e) {
    
    
    Log.i("事务处理失败", e.toString());
}finally {
    
    
    db.endTransaction();	//关闭事务
    db.close();		//关闭数据库
}

3、实战演练:通讯录

布局文件activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<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:background="@drawable/background"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingTop="16dp"
    android:paddingBottom="16dp"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/ll_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="50dp"
        android:layout_alignLeft="@+id/ll_btn"
        android:layout_alignStart="@+id/ll_btn">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:textStyle="bold"
            android:text="姓  名:"/>
        <EditText
            android:id="@+id/et_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:textStyle="bold"
            android:hint="请输入姓名" />
    </LinearLayout>
    <LinearLayout
        android:id="@+id/ll_phone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:layout_below="@+id/ll_name"
        android:layout_alignLeft="@+id/ll_name"
        android:layout_alignStart="@+id/ll_name">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:textStyle="bold"
            android:text="电  话:" />
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:textStyle="bold"
            android:hint="请输入手机号:" />
    </LinearLayout>
    <LinearLayout
        android:id="@+id/ll_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/ll_phone"
        android:layout_centerVertical="true">
        <Button
            android:id="@+id/btn_add"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="18sp"
            android:background="#B9B9FF"
            android:layout_marginRight="2dp"
            android:text="添加" />
        <Button
            android:id="@+id/btn_query"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="18sp"
            android:background="#DCB5FF"
            android:layout_marginRight="2dp"
            android:text="查询" />
        <Button
            android:id="@+id/btn_update"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="18sp"
            android:background="#E6CAFF"
            android:layout_marginRight="2dp"
            android:text="修改" />
        <Button
            android:id="@+id/btn_delete"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="18sp"
            android:background="#ACD6FF"
            android:text="删除" />
    </LinearLayout>

    <TextView
        android:id="@+id/tv_show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/ll_btn"
        android:layout_marginTop="253dp"
        android:textSize="30sp" />
</RelativeLayout>

在这里插入图片描述
实现联系人信息的添加、查询、修改和删除MainActivity.java:

package edu.hzuapps.directory;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    
    
    MyHelper myHelper;
    private EditText editName;
    private EditText editPhone;
    private TextView tvShow;
    private Button btnAdd;
    private Button btnQuery;
    private Button btnUpdate;
    private Button btnDelete;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myHelper = new MyHelper(this);
        init();     //初始化控件
    }
    private void init() {
    
    
        editName = (EditText)findViewById(R.id.et_name);
        editPhone = (EditText)findViewById(R.id.et_phone);
        tvShow = (TextView)findViewById(R.id.tv_show);
        btnAdd = (Button)findViewById(R.id.btn_add);
        btnDelete = (Button)findViewById(R.id.btn_delete);
        btnQuery = (Button)findViewById(R.id.btn_query);
        btnUpdate = (Button)findViewById(R.id.btn_update);
        btnAdd.setOnClickListener(this);
        btnUpdate.setOnClickListener(this);
        btnQuery.setOnClickListener(this);
        btnDelete.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
    
    
        String name;
        String phone;
        SQLiteDatabase db;
        ContentValues values;
        switch (v.getId()) {
    
    
            case R.id.btn_add:  //添加数据
                name = editName.getText().toString();
                phone = editPhone.getText().toString();
                db = myHelper.getWritableDatabase();    //获取可读写SQLiteDatabase对象
                values = new ContentValues();
                values.put("name", name);
                values.put("phone",phone);
                db.insert("information", null, values);
                Toast.makeText(this,"信息已添加", Toast.LENGTH_SHORT).show();
                db.close();
                break;
            case R.id.btn_query:    //查询数据
                db = myHelper.getReadableDatabase();
                Cursor cursor = db.query("information", null, null, null, null, null, null);
                if(cursor.getCount() == 0) {
    
    
                    tvShow.setText("");
                    Toast.makeText(this, "未找到该联系人", Toast.LENGTH_SHORT).show();
                } else {
    
    
                    cursor.moveToFirst();
                    tvShow.setText("Name:"+cursor.getString(1)+"  Tel:"+cursor.getString(2));
                }
                while (cursor.moveToNext()) {
    
    
                    tvShow.append("\n"+"Name:"+cursor.getString(1)+"  Tel:"+cursor.getString(2));
                }
                cursor.close();
                db.close();
                break;
            case R.id.btn_update:   //修改数据
                db = myHelper.getWritableDatabase();
                values = new ContentValues();   //要修改的数据
                values.put("phone", phone = editPhone.getText().toString());
                db.update("information", values, "name=?", new String[]{
    
    editName.getText().toString()});    //更新并得到行数
                Toast.makeText(this, "联系人信息已修改", Toast.LENGTH_SHORT).show();
                db.close();
                break;
            case R.id.btn_delete:   //删除数据
                db = myHelper.getWritableDatabase();
                db.delete("information", "name=?", new String[]{
    
    editName.getText().toString()});
                Toast.makeText(this, "联系人信息已删除", Toast.LENGTH_SHORT).show();
                tvShow.setText("");
                db.close();
                break;
        }
    }
}
class MyHelper extends SQLiteOpenHelper {
    
    
    public MyHelper(Context context) {
    
    
        super(context, "hzuapps.db",null,1);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
    
    
        db.execSQL("CREATE TABLE information(_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(20), phone VARCHAR(20))");
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    
    
    }
}

在这里插入图片描述
在这里插入图片描述

四、数据展示监控

1、ListView控件

ListView用来展示具体数据内容,当数据过多时会出现滚动条,并且能够根据数据的长度自适应屏幕显示。
activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".MainActivity">
    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>
</RelativeLayout>

在这里插入图片描述

2、常用数据适配器

(1)BaseAdapter:基本适配器

方法名称 功能描述
public int getCount() 得到Item条目的总数
public Object getItem(int position) 根据position位置得到某个Item的对象
public long getItemId(int position) 根据position位置得到摸个Item的ID
public View getView(int position, View convertView, ViewGroup parent) 得到相应position对应的Item视图,position是当前Item的位置,convertView用于复用旧视图,parent用于加载XML布局

(2)SimpleAdapter:继承自BaseAdapter

public SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to);
  • Context context:语境,上下文对象。
  • List<? extends Map

(3)ArrayAdapter:继承自BaseAdapter

ArrayAdapter通常用于适配TextView控件,例如设置菜单:

public ArrayAdapter(Context context, int resource);
public ArrayAdapter(Context context, int resource, int textViewResourceId);
public ArrayAdapter(Context context, int resource, T[] objects);
public ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects);
public ArrayAdapter(Context context, int resource, List<T> objects);
public ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects);

  • Context context:语境,上下文对象。
  • int textViewResourceId:Item布局中相应的TextView的id。
  • int resource:Item布局的资源id。
  • T[] objects:需要适配的数据数组,数组类型数据。
  • List<T> objects:需要适配的数据数组,List类型数据。

3、实战演练:Android应用市场

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".MainActivity">
    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="5dp"
        android:dividerHeight="1dp">
    </ListView>
</RelativeLayout>

list_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:gravity="center_vertical">
    <ImageView
        android:id="@+id/iv"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_margin="8dp"
        android:background="@drawable/background" />
    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ListView的Item布局"
        android:textSize="18sp" />
</LinearLayout>

MainActivity.java:

package edu.hzuapps.applicationmarket;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    
    
    private ListView listView;
    //需要适配的数据
    private String[] names = {
    
    "京东商城", "QQ", "QQ斗地主", "新浪微博", "天猫", "UC浏览器", "微信"};
    //图片集合
    private int[] icons = {
    
    R.drawable.jd, R.drawable.qq, R.drawable.qqddz, R.drawable.xl, R.drawable.tm, R.drawable.uc, R.drawable.wx};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化ListView控件
        listView = (ListView) findViewById(R.id.lv);
        //创建一个Adapter实例
        MyBaseAdapter myBaseAdapter = new MyBaseAdapter();
        //设置Adapter
        listView.setAdapter(myBaseAdapter);
    }
    class MyBaseAdapter extends BaseAdapter {
    
    
        //得到item的总数
        @Override
        public int getCount() {
    
    
            //返回ListView Item条目的总数
            return names.length;
        }
        //得到Item代表的对象
        @Override
        public Object getItem(int position) {
    
    
            //返回ListView Item代表的对象
            return names[position];
        }
        //得到Item的id
        @Override
        public long getItemId(int position) {
    
    
            return position;
        }
        //得到Item的View视图
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
    
    
            //将list_item.xml文件找出来并转换成View对象
            View view = View.inflate(MainActivity.this, R.layout.list_item, null);
            TextView textView = (TextView) view.findViewById(R.id.tv);
            textView.setText(names[position]);
            ImageView imageView = (ImageView) view.findViewById(R.id.iv);
            imageView.setBackgroundResource(icons[position]);
            return view;
        }
    }
}

在这里插入图片描述

4、ListView的优化

如果展示的数据有成千上万条,那么需要创建成千上万个Item,会大大增加内存的消耗。ListView优化的两种方式:复用convertView,使用ViewHolder类。

(1)复用convertView

当滑动ListView时,顶部的Item会滑出屏幕,同时释放convertView,只要固定convertView即可避免每次创建Item而消耗的内存。

(2)使用ViewHolder类

在加载Item布局时,会使用findViewById方法找到Item中的各个控件,比较耗时,因此可以将要加载的子View放入ViewHolder中,第一次创建convertView时将这些控件找出,第二次直接通过getTag方法获取。在LayoutInflater.from方法需要传入一个Context对象作为参数,在Adapter中获取Context对象需要使用getApplicationContext方法。

public View getView(int position, View convertView, ViewGroup parent) {
    
    
            ViewHolder viewHolder;
            if(convertView == null) {
    
    
                convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_item, parent, false);
                viewHolder = new ViewHolder();
                viewHolder.textView.setText(names[position]);
                viewHolder.imageView.setBackgroundResource(icons[position]);
                convertView.setTag(viewHolder);
            } else {
    
    
                viewHolder = (ViewHolder) convertView.getTag();
            }
            viewHolder.textView.setText(names[position]);
            viewHolder.imageView.setBackgroundResource(icons[position]);
            return convertView;
        }
        class ViewHolder {
    
    
            TextView textView;
            ImageView imageView;
        }

猜你喜欢

转载自blog.csdn.net/weixin_44047795/article/details/111772551