SQLite(三)项目之增加和显示联系人列表

164 阅读4分钟

这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战

项目目录

在这里插入图片描述
效果图:
在这里插入图片描述

联系人添加

第一个页面 MainActivity 对应的布局 activity_main

<?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="vertical">

    <Button
        android:id="@+id/btn_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="添加联系人" />

    <ListView
        android:id="@+id/lv_contacts"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

我们可以用一个 DBOpenHelper 来帮助我们管理数据库,以免反复执行出错:

public class DBOpenHelper extends SQLiteOpenHelper {

    /*public DBOpenHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }*/
    //修改原来的构造方法
    public DBOpenHelper(Context context) {
        super(context, "test.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //当创建数据库时,直接创建数据表
        String sql = "CREATE TABLE users (" +
                "_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
                "_name VARCHAR(10) UNIQUE NOT NULL, " +
                "_age INTEGER, " +
                "_phone CHAR(11), " +
                "_email VARCHAR(31) UNIQUE" +
                ")";
        db.execSQL(sql);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //升级时
    }
}

DBOpenHelper的onCreate()方法确保创建数据库的时候执行,不创建的时候不反复执行

MainActivity

public class ContactFormActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btn_add;
    private ListView lv_contacts;

    SQLiteOpenHelper s;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();

        DBOpenHelper dbOpenHelper = new DBOpenHelper(this);
        //必须调用以下其中一个方法才能执行创建数据库
        //dbOpenHelper.getReadableDatabase();
        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    }

    private void initView() {
        btn_add = findViewById(R.id.btn_add);
        lv_contacts = findViewById(R.id.lv_contacts);

        btn_add.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        Intent intent = new Intent(this, ContactFormActivity.class);
        startActivity(intent);
    }
}

第二个页面 ContactFormActivity 对应的布局 activity_contact_form

<?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="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="请输入联系人信息" />

    <EditText
        android:id="@+id/et_username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入联系人姓名"
        android:inputType="text" />

    <EditText
        android:id="@+id/et_age"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入联系人年龄"
        android:inputType="number" />

    <EditText
        android:id="@+id/et_phone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入联系人电话"
        android:inputType="number" />

    <EditText
        android:id="@+id/et_email"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入联系人Email"
        android:inputType="text" />

    <Button
        android:id="@+id/btn_save"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="保存" />

    <Button
        android:id="@+id/btn_back"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="返回" />
</LinearLayout>

创建一个 Person

public class Person {
    private String name;
    private int age;
    private String phone;
    private String email;

    public Person() {
    }

    public Person(String name, int age, String phone, String email) {
        this.name = name;
        this.age = age;
        this.phone = phone;
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

创建接口 IDao,实现相关功能

public interface IDao<T> {
    long insert(T t);
}

创建 PersonDao

public class PersonDao implements IDao<Person> {
    private Context context;

    public PersonDao(Context context) {
        setContext(context);
    }

    private void setContext(Context context) {
        if (context == null) {
            throw new IllegalArgumentException("参数context不能为空");
        }
        this.context = context;
    }

    @Override
    public long insert(Person person) {
        //获取SQLiteDatabase对象
        DBOpenHelper dbOpenHelper = new DBOpenHelper(context);
        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
        //执行业务,增加数据
        String table = "users";
        String nullColumnHack = "_id";
        ContentValues values = new ContentValues();
        values.put("_name", person.getName());
        values.put("_age", person.getAge());
        values.put("_phone", person.getPhone());
        values.put("_email", person.getEmail());
        long id = db.insert(table, nullColumnHack, values);

        //释放资源
        db.close();
        db = null;
        //返回
        return id;
    }
}

ContractFormActivity

public class ContactFormActivity extends AppCompatActivity implements View.OnClickListener {
    private EditText etUsername;
    private EditText etAge;
    private EditText etPhone;
    private EditText etEmail;
    private Button btnSave;
    private Button btnBack;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_contact_form);

        initViews();
        setListeners();
    }

    private void setListeners() {
        btnSave.setOnClickListener(this);
        btnBack.setOnClickListener(this);
    }

    private void initViews() {
        etUsername = findViewById(R.id.et_username);
        etAge = findViewById(R.id.et_age);
        etPhone = findViewById(R.id.et_phone);
        etEmail = findViewById(R.id.et_email);
        btnSave = findViewById(R.id.btn_save);
        btnBack = findViewById(R.id.btn_back);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_save:
                //获取表单中的数据
                String name = etUsername.getText().toString().trim();
                String phone = etPhone.getText().toString().trim();
                String email = etEmail.getText().toString().trim();
                int age = Integer.parseInt(etAge.getText().toString());

                Person person = new Person(name, age, phone, email);
                PersonDao personDao = new PersonDao(this);
                long id = personDao.insert(person);
                if (id == -1) {
                    Toast.makeText(this, "姓名或电子邮件可能冲突!", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this, "数据增加成功", Toast.LENGTH_SHORT).show();
                    etUsername.setText(null);
                    etPhone.setText(null);
                    etEmail.setText(null);
                    etAge.setText(null);
                }
                break;
            case R.id.btn_back:
                finish();
                break;
        }
    }
}

运行程序
在这里插入图片描述

联系人查询

IDao 中增加查询方法

public interface IDao<T> {
    long insert(T t);

    List<T> query(String whereClause, String[] whereArgs, String orderBy);
}

PersonDao中完善query()方法

@Override
    public List<Person> query(String whereClause, String[] whereArgs, String orderBy) {
        //声明返回值
        List<Person> persons = new ArrayList<Person>();
        //获取SQLiteDatabase对象
        DBOpenHelper dbOpenHelper = new DBOpenHelper(context);
        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();

        //执行业务:查询数据
        String table = "users";
        String[] columns = {"_id", "_name", "_age", "_phone", "_email"};
        Cursor c = db.query(table, columns, whereClause, whereArgs, null, null, orderBy);
        //将数据封装到返回值中
        for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
            Person p = new Person();
            p.setId(c.getInt(0));
            p.setName(c.getString(1));
            p.setAge(c.getInt(2));
            p.setPhone(c.getString(3));
            p.setEmail(c.getString(4));
            persons.add(p);
        }
        //释放资源
        db.close();
        db = null;
        //返回
        return persons;
    }

因为查询字段中有 id 字段,所以 Person 类中增加 id 字段

public class Person {
    private int id;
    private String name;
    private int age;
    private String phone;
    private String email;

    public Person() {
    }

    public Person(String name, int age, String phone, String email) {
        this.name = name;
        this.age = age;
        this.phone = phone;
        this.email = email;
    }

    public Person(int id, String name, int age, String phone, String email) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.phone = phone;
        this.email = email;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
	......
}

新建 PersonAdapter

public class PersonAdapter extends BaseAdapter {
    public PersonAdapter(Context context, List data) {
        super(context, data);
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        //2.声明ViewHolder对象
        ViewHolder viewHolder = null;
        //3.判断view
        if (view == null) {
            viewHolder = new ViewHolder();
            view = getInflater().inflate(R.layout.item_contact, null);
            viewHolder.tvName = view.findViewById(R.id.tv_name);
            viewHolder.tvAge = view.findViewById(R.id.tv_age);
            viewHolder.tvPhone = view.findViewById(R.id.tv_phone);
            viewHolder.tvEmail = view.findViewById(R.id.tv_email);

            view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) view.getTag();
        }
        //4.根据参数position确定需要显示的数据
        Person p = (Person) getData().get(i);

        //5.向控件中填充数据
        viewHolder.tvName.setText(p.getName());
        viewHolder.tvAge.setText(p.getAge() + "");
        viewHolder.tvPhone.setText(p.getPhone());
        viewHolder.tvEmail.setText(p.getEmail());
        return view;
    }

    //1.声明ViewHolder类
    class ViewHolder {
        TextView tvName;
        TextView tvAge;
        TextView tvPhone;
        TextView tvEmail;
    }
}

其中 BaseAdapter 我们在之前的项目中写过,直接拿过来用就可以了:传送门

item 的布局 item_contact.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="vertical"
    android:padding="20dp">

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tv_age"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tv_phone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tv_email"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

MainActivity

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btn_add;
    private ListView lv_contacts;
    private List<Person> persons;
    private PersonAdapter adapter;

    SQLiteOpenHelper s;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();

        DBOpenHelper dbOpenHelper = new DBOpenHelper(this);
        //必须调用以下其中一个方法才能执行创建数据库
        //dbOpenHelper.getReadableDatabase();
        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
        //获取数据源
        PersonDao personDao = new PersonDao(this);
        persons = personDao.query(null, null, "_name ASC");
        adapter = new PersonAdapter(this, persons);
        lv_contacts.setAdapter(adapter);
    }

    private void initView() {
        btn_add = findViewById(R.id.btn_add);
        lv_contacts = findViewById(R.id.lv_contacts);

        btn_add.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        Intent intent = new Intent(this, ContactFormActivity.class);
        startActivity(intent);
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        //获取新的数据,刷新列表
        PersonDao personDao = new PersonDao(this);
        persons.clear();
        persons.addAll(personDao.query(null, null, "_name ASC"));
        adapter.notifyDataSetChanged();
    }
}

运行程序
在这里插入图片描述