经过了一上午的折腾,大致了解了如何开发一个疫情每日登录APP,首先我们需要使用数据库存储数据,Android Studio自带了SQLite作为数据库,可以通过DataBaseHelper来实现,但毕竟还是有些繁琐。今天主要学习了Google的数据库框架Room框架,Room框架由三部分组成,Entity(实体)、Dao(操作接口层)、DataBase(继承了RoomDatabase的自定义类),下面是一个小demo:
首先是Entity
package com.michael.roomdemo.database; import androidx.room.ColumnInfo; import androidx.room.Entity; import androidx.room.Ignore; import androidx.room.PrimaryKey; /** * Model * */ @Entity(tableName = "student") public class Student { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER) public int id; @ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT) public String name; @ColumnInfo(name = "age", typeAffinity = ColumnInfo.TEXT) public String age; /** * Room会使用这个构造器来存储数据,也就是当你从表中得到Student对象时候,Room会使用这个构造器 * */ public Student(int id, String name, String age) { this.id = id; this.name = name; this.age = age; } /** * 由于Room只能识别和使用一个构造器,如果希望定义多个构造器,你可以使用Ignore标签,让Room忽略这个构造器 * 同样,@Ignore标签还可用于字段,使用@Ignore标签标记过的字段,Room不会持久化该字段的数据 * */ @Ignore public Student(String name, String age) { this.name = name; this.age = age; } }
- 这里需要使用
@Entity
来注解该类 - 至少要有一个主键
@PrimaryKey
然后是Dao层:
package com.michael.roomdemo.database; import java.util.List; import androidx.room.Dao; import androidx.room.Delete; import androidx.room.Insert; import androidx.room.Query; import androidx.room.Update; /** * DAO * * 对数据库表的增删改查 * * */ @Dao public interface StudentDao { @Insert void insertStudent(Student student); @Delete void deleteStudent(Student student); @Update void updateStudent(Student student); @Query("SELECT * FROM student") List<Student> getStudentList(); @Query("SELECT * FROM student WHERE id = :id") Student getStudentById(int id); }
- 使用
@Dao
注解该接口 @Insert
,@Update
,@Delete
,@Query
代表我们常用的插入
、更新
、删除
、查询
数据库操作@Insert
,@Update
,@Delete
可以传入多种不同的参数。@Query
也可以返回多种不同的类型。
然后是我们的自定义数据库:
package com.michael.roomdemo.database; import android.content.Context; import androidx.room.Database; import androidx.room.Room; import androidx.room.RoomDatabase; @Database(entities = {Student.class}, version = 1,exportSchema = false) public abstract class MyDatabase extends RoomDatabase { private static final String DATABASE_NAME = "my_db"; private static MyDatabase databaseInstance; public static synchronized MyDatabase getInstance(Context context) { if(databaseInstance == null) { databaseInstance = Room .databaseBuilder(context.getApplicationContext(), MyDatabase.class, DATABASE_NAME) .build(); } return databaseInstance; } public abstract StudentDao studentDao(); }
在定义好这些基本操作后,我们来看看界面:
界面比较简陋,主要是点击添加student后就弹出添加的activity
然后长按列表元素后会触发事件,有更新和删除选项,依次弹出相应的activity
前台代码就不放了,主要放一下后台:
package com.michael.roomdemo; import android.content.DialogInterface; import android.os.AsyncTask; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.AdapterView; import android.widget.EditText; import android.widget.ListView; import android.widget.Toast; import com.michael.roomdemo.database.MyDatabase; import com.michael.roomdemo.database.Student; import java.util.ArrayList; import java.util.List; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private MyDatabase myDatabase; private List<Student> studentList; private StudentAdapter studentAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btnInsertStudent).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { openAddStudentDialog(); } }); ListView lvStudent = findViewById(R.id.lvStudent); studentList = new ArrayList<>(); studentAdapter = new StudentAdapter(MainActivity.this, studentList); lvStudent.setAdapter(studentAdapter); lvStudent.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { updateOrDeleteDialog(studentList.get(position)); return false; } }); myDatabase = MyDatabase.getInstance(this); new QueryStudentTask().execute(); } //弹出选择是删除还是更新的选择框 private void updateOrDeleteDialog(final Student student) { final String[] options = new String[]{"更新", "删除"}; new AlertDialog.Builder(MainActivity.this) .setTitle("") .setItems(options, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if(which == 0) { openUpdateStudentDialog(student); } else if(which == 1) { new DeleteStudentTask(student).execute(); } } }).show(); } //弹出添加学生的Dialog private void openAddStudentDialog() { View customView = this.getLayoutInflater().inflate(R.layout.dialog_layout_student, null); final EditText etName = customView.findViewById(R.id.etName); final EditText etAge = customView.findViewById(R.id.etAge); final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); AlertDialog dialog = builder.create(); dialog.setTitle("Add Student"); dialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (TextUtils.isEmpty(etName.getText().toString()) || TextUtils.isEmpty(etAge.getText().toString())) { Toast.makeText(MainActivity.this, "输入不能为空", Toast.LENGTH_SHORT).show(); } else { new InsertStudentTask(etName.getText().toString(), etAge.getText().toString()).execute(); } } }); dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "CANCEL", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); dialog.setView(customView); dialog.show(); } //弹出更改学生信息的dialog private void openUpdateStudentDialog(final Student student) { if (student == null) { return; } View customView = this.getLayoutInflater().inflate(R.layout.dialog_layout_student, null); final EditText etName = customView.findViewById(R.id.etName); final EditText etAge = customView.findViewById(R.id.etAge); etName.setText(student.name); etAge.setText(student.age); final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); AlertDialog dialog = builder.create(); dialog.setTitle("Update Student"); dialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (TextUtils.isEmpty(etName.getText().toString()) || TextUtils.isEmpty(etAge.getText().toString())) { Toast.makeText(MainActivity.this, "输入不能为空", Toast.LENGTH_SHORT).show(); } else { new UpdateStudentTask(student.id, etName.getText().toString(), etAge.getText().toString()).execute(); } } }); dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "CANCEL", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); dialog.setView(customView); dialog.show(); } //插入的异步操作 private class InsertStudentTask extends AsyncTask<Void, Void, Void> { String name; String age; public InsertStudentTask(final String name, final String age) { this.name = name; this.age = age; } @Override protected Void doInBackground(Void... arg0) { myDatabase.studentDao().insertStudent(new Student(name, age)); studentList.clear(); studentList.addAll(myDatabase.studentDao().getStudentList()); return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); studentAdapter.notifyDataSetChanged(); } } //更新的异步操作 private class UpdateStudentTask extends AsyncTask<Void, Void, Void> { int id; String name; String age; public UpdateStudentTask(final int id, final String name, final String age) { this.id = id; this.name = name; this.age = age; } @Override protected Void doInBackground(Void... arg0) { myDatabase.studentDao().updateStudent(new Student(id, name, age)); studentList.clear(); studentList.addAll(myDatabase.studentDao().getStudentList()); return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); studentAdapter.notifyDataSetChanged(); } } //删除的异步操作 private class DeleteStudentTask extends AsyncTask<Void, Void, Void> { Student student; public DeleteStudentTask(Student student) { this.student = student; } @Override protected Void doInBackground(Void... arg0) { myDatabase.studentDao().deleteStudent(student); studentList.clear(); studentList.addAll(myDatabase.studentDao().getStudentList()); return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); studentAdapter.notifyDataSetChanged(); } } //异步显示全部学生信息 private class QueryStudentTask extends AsyncTask<Void, Void, Void> { public QueryStudentTask() { } @Override protected Void doInBackground(Void... arg0) { studentList.clear(); studentList.addAll(myDatabase.studentDao().getStudentList()); return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); studentAdapter.notifyDataSetChanged(); } } }
这是主要后台,可以看注释
适应器代码:
package com.michael.roomdemo; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.michael.roomdemo.database.Student; import java.util.List; public class StudentAdapter extends BaseAdapter { private List<Student> data; private LayoutInflater layoutInflater; public StudentAdapter(Context context, List<Student> data) { this.data = data; layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } class ViewHolder { TextView tvId; TextView tvName; TextView tvAge; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { convertView = layoutInflater.inflate(R.layout.list_item_student, null); viewHolder = new ViewHolder(); viewHolder.tvId = convertView.findViewById(R.id.tvId); viewHolder.tvName = convertView.findViewById(R.id.tvName); viewHolder.tvAge = convertView.findViewById(R.id.tvAge); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.tvId.setText(String.valueOf(data.get(position).id)); viewHolder.tvName.setText(data.get(position).name); viewHolder.tvAge.setText(data.get(position).age); return convertView; } @Override public int getCount() { if (data == null) { return 0; } return data.size(); } @Override public Student getItem(int position) { return data.get(position); } @Override public long getItemId(int position) { return position; } }