本项目是RecyclerView与SQLite结合的尝试。
实现的操作是输入两个String类型的数据进入数据库并进行相应操作,两个数据分别为name(主键)和age。
数据库操作类
首先定义一个数据库操作类命名为DataHelper,里面包含数据库的创建,主键的定义,以及增删改查等需要修改或者读取数据库操作的函数方法。
创建数据库并且命名
public DataHelper(Context context) {
super(context, "UserData.db", null, 1);
}//这里的名字是数据库的名字
创建表格,命名,同时确定主键
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE UserDetails(name TEXT primary key,age TEXT)");//UserDetails是table名字,name是主键
}
数据库版本信息
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
创建几个一会要应用于数据库中的函数方法:插入,查询,删除
插入方法
public Boolean InsertUserdata(String name,String age)
{
SQLiteDatabase sqLiteDatabase=this.getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put("name",name);
cv.put("age",age);
long result=sqLiteDatabase.insert("UserDetails",null,cv);
if(result==-1)
{
return false;
}
sqLiteDatabase.close();
return true;
}
附上官方文档中insert函数的编写方法
查阅数据/取得数据
public Cursor getData()
{
SQLiteDatabase sqLiteDatabase=this.getWritableDatabase();
Cursor cursor=sqLiteDatabase.rawQuery("SELECT * FROM UserDetails",null);
return cursor;
}
删除数据
public Boolean DeleteUserdata(String name)
{
SQLiteDatabase sqLiteDatabase=this.getWritableDatabase();
int delete=sqLiteDatabase.delete("UserDetails","name"+"=?",new String[]{String.valueOf(name)});
if(delete==1)
{
return true;
}
else
{
return false;
}
}
附上官方文档中的delete方法
编辑数据
public Boolean updateData(String name,String age)
{
ContentValues cv=new ContentValues();
cv.put("name",name);
cv.put("age",age);
SQLiteDatabase sqLiteDatabase=this.getWritableDatabase();
// 打印调试信息
int update=sqLiteDatabase.update("UserDetails",cv,"name"+"=?",new String[]{String.valueOf(name)});
if(update==0)
{
return false;
}
else
{
return true;
}
}
官方文档中update方法
给出整体代码
package com.example.recyclerviewwithsqlite;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
import java.util.ArrayList;
public class DataHelper extends SQLiteOpenHelper {
public DataHelper(Context context) {
super(context, "UserData.db", null, 1);
}//这里的名字是数据库的名字
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE UserDetails(name TEXT primary key,age TEXT)");//UserDetails是table名字,name是主键
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public Boolean InsertUserdata(String name,String age)
{
SQLiteDatabase sqLiteDatabase=this.getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put("name",name);
cv.put("age",age);
long result=sqLiteDatabase.insert("UserDetails",null,cv);
if(result==-1)
{
return false;
}
sqLiteDatabase.close();
return true;
}
public Cursor getData()
{
SQLiteDatabase sqLiteDatabase=this.getWritableDatabase();
Cursor cursor=sqLiteDatabase.rawQuery("SELECT * FROM UserDetails",null);
return cursor;
}
public Boolean DeleteUserdata(String name)
{
SQLiteDatabase sqLiteDatabase=this.getWritableDatabase();
int delete=sqLiteDatabase.delete("UserDetails","name"+"=?",new String[]{String.valueOf(name)});
if(delete==1)
{
return true;
}
else
{
return false;
}
}
public Boolean updateData(String name,String age)
{
ContentValues cv=new ContentValues();
cv.put("name",name);
cv.put("age",age);
SQLiteDatabase sqLiteDatabase=this.getWritableDatabase();
// 打印调试信息
int update=sqLiteDatabase.update("UserDetails",cv,"name"+"=?",new String[]{String.valueOf(name)});
if(update==0)
{
return false;
}
else
{
return true;
}
}
}
首页
首页包括输入姓名数据和年龄数据,对于数据库增删查操作的触发按钮,另外改的操作会在别的页面中触发
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="56dp"
android:text="输入信息"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.149"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="72dp"
android:ems="10"
android:hint="输入姓名"
android:inputType="text"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.496"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text" />
<EditText
android:id="@+id/age"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="168dp"
android:ems="10"
android:hint="输入年龄"
android:inputType="text"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.496"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text" />
<Button
android:id="@+id/btnInsert"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:text="插入数据"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.179"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text" />
<Button
android:id="@+id/btnView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="400dp"
android:text="view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text" />
<Button
android:id="@+id/btndelete"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="500dp"
android:text="删除数据"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text" />
</androidx.constraintlayout.widget.ConstraintLayout>
接下来是首页的功能
package com.example.recyclerviewwithsqlite;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
EditText name,age;
Button insert,view,delete;
DataHelper dataHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name=findViewById(R.id.name);
age=findViewById(R.id.age);
insert=findViewById(R.id.btnInsert);
view=findViewById(R.id.btnView);
delete=findViewById(R.id.btndelete);
dataHelper=new DataHelper(MainActivity.this);
insert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String nametext=name.getText().toString();
String agetext=age.getText().toString();
Boolean insertresult=dataHelper.InsertUserdata(nametext,agetext);
if(insertresult==true)
{
Toast.makeText(MainActivity.this,"创建用户数据成功",Toast.LENGTH_SHORT).show();
}
else
{
//已有数据
Toast.makeText(MainActivity.this,"已有此用户,创建用户数据失败",Toast.LENGTH_SHORT).show();
}
}
});
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(MainActivity.this, Userlist.class);
startActivity(intent);
}
});
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String nametext=name.getText().toString();
Boolean deleteresult=dataHelper.DeleteUserdata(nametext);
if(deleteresult==true)
{
Toast.makeText(MainActivity.this,"删除"+nametext+"数据成功",Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(MainActivity.this,"删除失败,无对应数据",Toast.LENGTH_SHORT).show();
}
}
});
}
}
其中,点击插入按钮之后,通过获取文本框的姓名和年龄数据,同时调用数据库操作类中的插入方法实现新建数据。
因为姓名为主键,所以同一个姓名只能有一个对应的年龄,否则无法创建数据。
点击浏览按钮后跳转到Userlist界面执行其他操作
点击删除按钮后,通过姓名数据,删除数据库中对应的姓名和年龄,如果原本没有对应的姓名则会提示删除失败
RecyclerView Adapter
数据库中的信息是存在于RecyclerView中的,所以之前提到的Userlist界面整体就是一个RecyclerView
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Userlist">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
这个组件中包含了很多item,每一个item都对应了一组数据库的完整信息,即姓名与年龄。所以要首先创建一个item的xml文件来实现对每一组数据的展示
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="30dp">
<TextView
android:id="@+id/textname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="80dp"
android:text="TextView"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.208"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="68dp"
android:text="TextView"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="@+id/textname"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/textname"
app:layout_constraintTop_toBottomOf="@+id/textname" />
<Button
android:id="@+id/btnedit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="124dp"
android:text="修改信息"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.496"
app:layout_constraintStart_toEndOf="@+id/textname"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
每一个item的功能则是由创建的MyAdapter定义
MyAdapter完整代码
package com.example.recyclerviewwithsqlite;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
//Recyclerview的适配器
private Context context;
private ArrayList<String> name_id,age_id;
private OnItemClickListener listener;
public interface OnItemClickListener {
void onNameClick(String name);
void onAgeClick(String age);
}
public MyAdapter(Context context, ArrayList<String> name_id, ArrayList<String> age_id,OnItemClickListener listener) {
this.context = context;
this.name_id = name_id;
this.age_id = age_id;
this.listener=listener;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(this.context).inflate(R.layout.item,parent,false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
//在MyViewHolder添加完组件对象之后写
holder.name_id.setText(String.valueOf(name_id.get(position)));
holder.age_id.setText(String.valueOf(age_id.get(position)));
}
@Override
public int getItemCount() {
return this.name_id.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView name_id,age_id;
Button editBtn;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
name_id=itemView.findViewById(R.id.textname);
age_id=itemView.findViewById(R.id.textage);
editBtn=itemView.findViewById(R.id.btnedit);
editBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//注意适配器中点击事件和页面跳转与其他的不同
Intent intent=new Intent(context, edit.class);
//传数据至新的页面中
intent.putExtra("name",name_id.getText());;
intent.putExtra("age",age_id.getText());
context.startActivity(intent);
}
});
//给name_id age_id设置点击监听器,可以通过上面的OnItemClickListener接口里的方法,实现从外部获取name age中的文本信息
name_id.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION && listener != null)
{
listener.onNameClick(name_id.getText().toString());
}
}
});
age_id.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION && listener != null)
{
listener.onAgeClick(age_id.getText().toString());
}
}
});
}
}
}
其中,
-
MyAdapter 继承自
RecyclerView.Adapter<MyAdapter.MyViewHolder>
,用于提供RecyclerView
列表的数据。 -
context
用于访问应用程序的环境和资源。 -
name_id
和age_id
是存储名字和年龄的ArrayList
。 -
listener
是点击事件的监听器接口,用于处理名字和年龄的点击事件。
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context context;
private ArrayList<String> name_id, age_id;
private OnItemClickListener listener;
public interface OnItemClickListener {
void onNameClick(String name);
void onAgeClick(String age);
}
初始化适配器时传入 context
、名字列表、年龄列表和点击事件监听器。
public MyAdapter(Context context, ArrayList<String> name_id, ArrayList<String> age_id, OnItemClickListener listener) {
this.context = context;
this.name_id = name_id;
this.age_id = age_id;
this.listener = listener;
}
onCreateViewHolder
方法创建 MyViewHolder
实例,用于显示每一项数据。通过 LayoutInflater
从布局文件 item
中加载视图。
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(this.context).inflate(R.layout.item, parent, false);
return new MyViewHolder(view);
}
onBindViewHolder
方法将数据绑定到 ViewHolder
上,将指定位置的名字和年龄设置到视图中。
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
holder.name_id.setText(String.valueOf(name_id.get(position)));
holder.age_id.setText(String.valueOf(age_id.get(position)));
}
getItemCount
返回列表中的项数。
@Override
public int getItemCount() {
return this.name_id.size();
}
MyViewHolder
内部类继承自 RecyclerView.ViewHolder
,用于保存每个列表项的视图组件(名字、年龄和编辑按钮)。
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView name_id, age_id;
Button editBtn;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
name_id = itemView.findViewById(R.id.textname);
age_id = itemView.findViewById(R.id.textage);
editBtn = itemView.findViewById(R.id.btnedit);
editBtn
的点击事件:创建一个 Intent
,启动 edit
活动,并将名字和年龄传递给新活动。
editBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(context, edit.class);
intent.putExtra("name", name_id.getText());
intent.putExtra("age", age_id.getText());
context.startActivity(intent);
}
});
name_id
和 age_id
的点击事件:获取当前项的位置,如果位置有效且监听器不为空,则调用相应的监听器方法来处理点击事件。
name_id.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION && listener != null) {
listener.onNameClick(name_id.getText().toString());
}
}
});
age_id.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION && listener != null) {
listener.onAgeClick(age_id.getText().toString());
}
}
});
}
}
}
Userlist
回到Userlist的功能之中
package com.example.recyclerviewwithsqlite;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.Toast;
import java.util.ArrayList;
public class Userlist extends AppCompatActivity {
//数据库展示页面
RecyclerView recyclerView;
ArrayList<String> name,age;
DataHelper db;
MyAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_userlist);
db=new DataHelper(Userlist.this);
name=new ArrayList<>();
age=new ArrayList<>();
recyclerView=findViewById(R.id.recyclerview);
myAdapter=new MyAdapter(this, name, age, new MyAdapter.OnItemClickListener() {
@Override
public void onNameClick(String name) {
Toast.makeText(Userlist.this,"点击了"+name+"的姓名",Toast.LENGTH_SHORT).show();
}
@Override
public void onAgeClick(String age) {
Toast.makeText(Userlist.this,"点击了年龄"+age,Toast.LENGTH_SHORT).show();
}
});
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
display();
}
private void display()
{
Cursor cursor= db.getData();
if(cursor.getCount()==0)
{
Toast.makeText(Userlist.this,"无数据",Toast.LENGTH_SHORT).show();
return;
}
else
{
while (cursor.moveToNext())
{
name.add(cursor.getString(0));
age.add(cursor.getString(1));
}
}
}
}
其中,重写了适配器中的姓名和年龄的点击方法,在点击每一组姓名和年龄后都会弹出相应的提示框
myAdapter=new MyAdapter(this, name, age, new MyAdapter.OnItemClickListener() {
@Override
public void onNameClick(String name) {
Toast.makeText(Userlist.this,"点击了"+name+"的姓名",Toast.LENGTH_SHORT).show();
}
@Override
public void onAgeClick(String age) {
Toast.makeText(Userlist.this,"点击了年龄"+age,Toast.LENGTH_SHORT).show();
}
});
编辑页面
最后是编辑页面,没有什么新的内容,完整展示如下
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".edit">
<EditText
android:id="@+id/editname_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:ems="10"
android:inputType="text"
android:text="姓名"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/editage_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="150dp"
android:ems="10"
android:inputType="text"
android:text="年龄"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editname_text" />
<Button
android:id="@+id/update_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:text="确定修改"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editname_text" />
</androidx.constraintlayout.widget.ConstraintLayout>
功能
package com.example.recyclerviewwithsqlite;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.Toast;
public class edit extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit);
Intent intent=getIntent();//接收MyAdapter传递过来的数据
String name=intent.getStringExtra("name");
String age=intent.getStringExtra("age");
EditText editname=findViewById(R.id.editname_text);
EditText editage=findViewById(R.id.editage_text);
editname.setText(name);
editage.setText(age);
Button updateBtn=findViewById(R.id.update_btn);
updateBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String newname=editname.getText().toString();
String newage=editage.getText().toString();
DataHelper dataHelper=new DataHelper(edit.this);
Boolean update=dataHelper.updateData(newname,newage);
if(update==true)
{
Toast.makeText(edit.this,"修改数据成功",Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(edit.this,"修改数据失败",Toast.LENGTH_SHORT).show();
}
Intent intent1=new Intent(edit.this,Userlist.class);
startActivity(intent1);
}
});
}
}
END
安卓开发自学笔记