应用程序中的数据可以通过不同的方式保存在用户的设备上。我们可以通过SQLite表,共享首选项以及更多方式将数据存储在用户设备中。在本文中,我们将研究如何在Android的Room Database中保存数据,读取,更新和删除数据。我们将使用Android上的Room Database执行CRUD操作。在本文中,我们将研究在Android的Room Database中执行CRUD操作。
我们将在本文中构建什么?
我们将构建一个简单的应用程序,在其中将添加Geeks for Geeks上可用的不同类型的课程。我们将所有这些数据存储在会议室数据库中,并对这些课程执行CRUD操作。下面提供了一个示例视频,以使您对我们在本文中将要做的事情有个大概的了解。注意,我们将使用Java语言实现该项目。
什么是房间?
Room是一个持久性库,它在SQLite数据库上提供了一个抽象层,以允许使用更强大的数据库。在会议室的帮助下,我们可以轻松地创建数据库并非常轻松地执行CRUD操作。
房间组成
房间的三个主要组成部分是Entity,Database和DAO 。
- 实体:实体是使用@Entity注释的模态类。该类具有的变量将是我们的列,而该类是我们的表。
- 数据库:这是一个抽象类,我们将在其中存储我们可以称为实体的所有数据库条目。
- DAO : DAO的完整形式是数据库访问对象,它是一个接口类,在它的帮助下,我们可以在数据库中执行不同的操作。
现在,让我们开始在Android中实现Room Database的实现。
分步实施
步骤1:创建一个新项目
要在Android Studio中创建新项目,请参阅如何在Android Studio中创建/启动新项目。请注意,选择Java作为编程语言。
步骤2:在build.gradle文件中添加使用Room的依赖关系
导航至应用程序> Gradle脚本> build.gradle文件,然后在“依赖项”部分中添加以下依赖项。
// add below dependancy for using room.
implementation ‘androidx.room:room-runtime:2.2.5’
annotationProcessor ‘androidx.room:room-compiler:2.2.5’
// add below dependancy for using lifecycle extensions for room.
implementation ‘androidx.lifecycle:lifecycle-extensions:2.2.0’
annotationProcessor ‘androidx.lifecycle:lifecycle-compiler:2.2.0’
添加以上依赖项部分之后。现在同步您的项目,我们将移至我们的XML文件。
步骤3:使用activity_main.xml文件
导航到应用程序> res>布局> activity_main.xml,然后将以下代码添加到该文件中。以下是activity_main.xml文件的代码。
XML
Java
import androidx.room.Entity;
import androidx.room.PrimaryKey;
// below line is for setting table name.
@Entity(tableName = "course_table")
public class CourseModal {
// below line is to auto increment
// id for each course.
@PrimaryKey(autoGenerate = true)
// variable for our id.
private int id;
// below line is a variable
// for course name.
private String courseName;
// below line is use for
// course description.
private String courseDescription;
// below line is use
// for course duration.
private String courseDuration;
// below line we are creating constructor class.
// inside constructor class we are not passing
// our id because it is incrementing automatically
public CourseModal(String courseName, String courseDescription, String courseDuration) {
this.courseName = courseName;
this.courseDescription = courseDescription;
this.courseDuration = courseDuration;
}
// on below line we are creating
// getter and setter methods.
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public String getCourseDescription() {
return courseDescription;
}
public void setCourseDescription(String courseDescription) {
this.courseDescription = courseDescription;
}
public String getCourseDuration() {
return courseDuration;
}
public void setCourseDuration(String courseDuration) {
this.courseDuration = courseDuration;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Java
import androidx.lifecycle.LiveData;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import java.util.List;
// Adding annotation
// to our Dao class
@androidx.room.Dao
public interface Dao {
// below method is use to
// add data to database.
@Insert
void insert(CourseModal model);
// below method is use to update
// the data in our database.
@Update
void update(CourseModal model);
// below line is use to delete a
// specific course in our database.
@Delete
void delete(CourseModal model);
// on below line we are making query to
// delete all courses from our database.
@Query("DELETE FROM course_table")
void deleteAllCourses();
// below line is to read all the courses from our database.
// in this we are ordering our courses in ascending order
// with our course name.
@Query("SELECT * FROM course_table ORDER BY courseName ASC")
LiveData> getAllCourses();
}
Java
import android.content.Context;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.sqlite.db.SupportSQLiteDatabase;
// adding annotation for our database entities and db version.
@Database(entities = {CourseModal.class}, version = 1)
public abstract class CourseDatabase extends RoomDatabase {
// below line is to create instance
// for our database class.
private static CourseDatabase instance;
// below line is to create
// abstract variable for dao.
public abstract Dao Dao();
// on below line we are getting instance for our database.
public static synchronized CourseDatabase getInstance(Context context) {
// below line is to check if
// the instance is null or not.
if (instance == null) {
// if the instance is null we
// are creating a new instance
instance =
// for creating a instance for our database
// we are creating a database builder and passing
// our database class with our database name.
Room.databaseBuilder(context.getApplicationContext(),
CourseDatabase.class, "course_database")
// below line is use to add fall back to
// destructive migration to our database.
.fallbackToDestructiveMigration()
// below line is to add callback
// to our database.
.addCallback(roomCallback)
// below line is to
// build our database.
.build();
}
// after creating an instance
// we are returning our instance
return instance;
}
// below line is to create a callback for our room database.
private static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
// this method is called when database is created
// and below line is to populate our data.
new PopulateDbAsyncTask(instance).execute();
}
};
// we are creating an async task class to perform task in background.
private static class PopulateDbAsyncTask extends AsyncTask {
PopulateDbAsyncTask(CourseDatabase instance) {
Dao dao = instance.Dao();
}
@Override
protected Void doInBackground(Void... voids) {
return null;
}
}
}
Java
import android.app.Application;
import android.os.AsyncTask;
import androidx.lifecycle.LiveData;
import java.util.List;
public class CourseRepository {
// below line is the create a variable
// for dao and list for all courses.
private Dao dao;
private LiveData> allCourses;
// creating a constructor for our variables
// and passing the variables to it.
public CourseRepository(Application application) {
CourseDatabase database = CourseDatabase.getInstance(application);
dao = database.Dao();
allCourses = dao.getAllCourses();
}
// creating a method to insert the data to our database.
public void insert(CourseModal model) {
new InsertCourseAsyncTask(dao).execute(model);
}
// creating a method to update data in database.
public void update(CourseModal model) {
new UpdateCourseAsyncTask(dao).execute(model);
}
// creating a method to delete the data in our database.
public void delete(CourseModal model) {
new DeleteCourseAsyncTask(dao).execute(model);
}
// below is the method to delete all the courses.
public void deleteAllCourses() {
new DeleteAllCoursesAsyncTask(dao).execute();
}
// below method is to read all the courses.
public LiveData> getAllCourses() {
return allCourses;
}
// we are creating a async task method to insert new course.
private static class InsertCourseAsyncTask extends AsyncTask {
private Dao dao;
private InsertCourseAsyncTask(Dao dao) {
this.dao = dao;
}
@Override
protected Void doInBackground(CourseModal... model) {
// below line is use to insert our modal in dao.
dao.insert(model[0]);
return null;
}
}
// we are creating a async task method to update our course.
private static class UpdateCourseAsyncTask extends AsyncTask {
private Dao dao;
private UpdateCourseAsyncTask(Dao dao) {
this.dao = dao;
}
@Override
protected Void doInBackground(CourseModal... models) {
// below line is use to update
// our modal in dao.
dao.update(models[0]);
return null;
}
}
// we are creating a async task method to delete course.
private static class DeleteCourseAsyncTask extends AsyncTask {
private Dao dao;
private DeleteCourseAsyncTask(Dao dao) {
this.dao = dao;
}
@Override
protected Void doInBackground(CourseModal... models) {
// below line is use to delete
// our course modal in dao.
dao.delete(models[0]);
return null;
}
}
// we are creating a async task method to delete all courses.
private static class DeleteAllCoursesAsyncTask extends AsyncTask {
private Dao dao;
private DeleteAllCoursesAsyncTask(Dao dao) {
this.dao = dao;
}
@Override
protected Void doInBackground(Void... voids) {
// on below line calling method
// to delete all courses.
dao.deleteAllCourses();
return null;
}
}
}
Java
import android.app.Application;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import java.util.List;
public class ViewModal extends AndroidViewModel {
// creating a new variable for course repository.
private CourseRepository repository;
// below line is to create a variable for live
// data where all the courses are present.
private LiveData> allCourses;
// constructor for our view modal.
public ViewModal(@NonNull Application application) {
super(application);
repository = new CourseRepository(application);
allCourses = repository.getAllCourses();
}
// below method is use to insert the data to our repository.
public void insert(CourseModal model) {
repository.insert(model);
}
// below line is to update data in our repository.
public void update(CourseModal model) {
repository.update(model);
}
// below line is to delete the data in our repository.
public void delete(CourseModal model) {
repository.delete(model);
}
// below method is to delete all the courses in our list.
public void deleteAllCourses() {
repository.deleteAllCourses();
}
// below method is to get all the courses in our list.
public LiveData> getAllCourses() {
return allCourses;
}
}
XML
Java
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;
public class CourseRVAdapter extends ListAdapter {
// creating a variable for on item click listener.
private OnItemClickListener listener;
// creating a constructor class for our adapter class.
CourseRVAdapter() {
super(DIFF_CALLBACK);
}
// creating a call back for item of recycler view.
private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() {
@Override
public boolean areItemsTheSame(CourseModal oldItem, CourseModal newItem) {
return oldItem.getId() == newItem.getId();
}
@Override
public boolean areContentsTheSame(CourseModal oldItem, CourseModal newItem) {
// below line is to check the course name, description and course duration.
return oldItem.getCourseName().equals(newItem.getCourseName()) &&
oldItem.getCourseDescription().equals(newItem.getCourseDescription()) &&
oldItem.getCourseDuration().equals(newItem.getCourseDuration());
}
};
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// below line is use to inflate our layout
// file for each item of our recycler view.
View item = LayoutInflater.from(parent.getContext())
.inflate(R.layout.course_rv_item, parent, false);
return new ViewHolder(item);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// below line of code is use to set data to
// each item of our recycler view.
CourseModal model = getCourseAt(position);
holder.courseNameTV.setText(model.getCourseName());
holder.courseDescTV.setText(model.getCourseDescription());
holder.courseDurationTV.setText(model.getCourseDuration());
}
// creating a method to get course modal for a specific position.
public CourseModal getCourseAt(int position) {
return getItem(position);
}
public class ViewHolder extends RecyclerView.ViewHolder {
// view holder class to create a variable for each view.
TextView courseNameTV, courseDescTV, courseDurationTV;
ViewHolder(@NonNull View itemView) {
super(itemView);
// initializing each view of our recycler view.
courseNameTV = itemView.findViewById(R.id.idTVCourseName);
courseDescTV = itemView.findViewById(R.id.idTVCourseDescription);
courseDurationTV = itemView.findViewById(R.id.idTVCourseDuration);
// adding on click listener for each item of recycler view.
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// inside on click listener we are passing
// position to our item of recycler view.
int position = getAdapterPosition();
if (listener != null && position != RecyclerView.NO_POSITION) {
listener.onItemClick(getItem(position));
}
}
});
}
}
public interface OnItemClickListener {
void onItemClick(CourseModal model);
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}
}
XML
Java
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class NewCourseActivity extends AppCompatActivity {
// creating a variables for our button and edittext.
private EditText courseNameEdt, courseDescEdt, courseDurationEdt;
private Button courseBtn;
// creating a constant string variable for our
// course name, description and duration.
public static final String EXTRA_ID = "com.gtappdevelopers.gfgroomdatabase.EXTRA_ID";
public static final String EXTRA_COURSE_NAME = "com.gtappdevelopers.gfgroomdatabase.EXTRA_COURSE_NAME";
public static final String EXTRA_DESCRIPTION = "com.gtappdevelopers.gfgroomdatabase.EXTRA_COURSE_DESCRIPTION";
public static final String EXTRA_DURATION = "com.gtappdevelopers.gfgroomdatabase.EXTRA_COURSE_DURATION";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_course);
// initializing our variables for each view.
courseNameEdt = findViewById(R.id.idEdtCourseName);
courseDescEdt = findViewById(R.id.idEdtCourseDescription);
courseDurationEdt = findViewById(R.id.idEdtCourseDuration);
courseBtn = findViewById(R.id.idBtnSaveCourse);
// below line is to get intent as we
// are getting data via an intent.
Intent intent = getIntent();
if (intent.hasExtra(EXTRA_ID)) {
// if we get id for our data then we are
// setting values to our edit text fields.
courseNameEdt.setText(intent.getStringExtra(EXTRA_COURSE_NAME));
courseDescEdt.setText(intent.getStringExtra(EXTRA_DESCRIPTION));
courseDurationEdt.setText(intent.getStringExtra(EXTRA_DURATION));
}
// adding on click listener for our save button.
courseBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// getting text value from edittext and validating if
// the text fields are empty or not.
String courseName = courseNameEdt.getText().toString();
String courseDesc = courseDescEdt.getText().toString();
String courseDuration = courseDurationEdt.getText().toString();
if (courseName.isEmpty() || courseDesc.isEmpty() || courseDuration.isEmpty()) {
Toast.makeText(NewCourseActivity.this, "Please enter the valid course details.", Toast.LENGTH_SHORT).show();
return;
}
// calling a method to save our course.
saveCourse(courseName, courseDesc, courseDuration);
}
});
}
private void saveCourse(String courseName, String courseDescription, String courseDuration) {
// inside this method we are passing
// all the data via an intent.
Intent data = new Intent();
// in below line we are passing all our course detail.
data.putExtra(EXTRA_COURSE_NAME, courseName);
data.putExtra(EXTRA_DESCRIPTION, courseDescription);
data.putExtra(EXTRA_DURATION, courseDuration);
int id = getIntent().getIntExtra(EXTRA_ID, -1);
if (id != -1) {
// in below line we are passing our id.
data.putExtra(EXTRA_ID, id);
}
// at last we are setting result as data.
setResult(RESULT_OK, data);
// displaying a toast message after adding the data
Toast.makeText(this, "Course has been saved to Room Database. ", Toast.LENGTH_SHORT).show();
}
}
Java
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.List;
public class MainActivity extends AppCompatActivity {
// creating a variables for our recycler view.
private RecyclerView coursesRV;
private static final int ADD_COURSE_REQUEST = 1;
private static final int EDIT_COURSE_REQUEST = 2;
private ViewModal viewmodal;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initializing our variable for our recycler view and fab.
coursesRV = findViewById(R.id.idRVCourses);
FloatingActionButton fab = findViewById(R.id.idFABAdd);
// adding on click listener for floating action button.
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// starting a new activity for adding a new course
// and passing a constant value in it.
Intent intent = new Intent(MainActivity.this, NewCourseActivity.class);
startActivityForResult(intent, ADD_COURSE_REQUEST);
}
});
// setting layout manager to our adapter class.
coursesRV.setLayoutManager(new LinearLayoutManager(this));
coursesRV.setHasFixedSize(true);
// initializing adapter for recycler view.
final CourseRVAdapter adapter = new CourseRVAdapter();
// setting adapter class for recycler view.
coursesRV.setAdapter(adapter);
// passing a data from view modal.
viewmodal = ViewModelProviders.of(this).get(ViewModal.class);
// below line is use to get all the courses from view modal.
viewmodal.getAllCourses().observe(this, new Observer>() {
@Override
public void onChanged(List models) {
// when the data is changed in our models we are
// adding that list to our adapter class.
adapter.submitList(models);
}
});
// below method is use to add swipe to delete method for item of recycler view.
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
// on recycler view item swiped then we are deleting the item of our recycler view.
viewmodal.delete(adapter.getCourseAt(viewHolder.getAdapterPosition()));
Toast.makeText(MainActivity.this, "Course deleted", Toast.LENGTH_SHORT).show();
}
}).
// below line is use to attach this to recycler view.
attachToRecyclerView(coursesRV);
// below line is use to set item click listener for our item of recycler view.
adapter.setOnItemClickListener(new CourseRVAdapter.OnItemClickListener() {
@Override
public void onItemClick(CourseModal model) {
// after clicking on item of recycler view
// we are opening a new activity and passing
// a data to our activity.
Intent intent = new Intent(MainActivity.this, NewCourseActivity.class);
intent.putExtra(NewCourseActivity.EXTRA_ID, model.getId());
intent.putExtra(NewCourseActivity.EXTRA_COURSE_NAME, model.getCourseName());
intent.putExtra(NewCourseActivity.EXTRA_DESCRIPTION, model.getCourseDescription());
intent.putExtra(NewCourseActivity.EXTRA_DURATION, model.getCourseDuration());
// below line is to start a new activity and
// adding a edit course constant.
startActivityForResult(intent, EDIT_COURSE_REQUEST);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ADD_COURSE_REQUEST && resultCode == RESULT_OK) {
String courseName = data.getStringExtra(NewCourseActivity.EXTRA_COURSE_NAME);
String courseDescription = data.getStringExtra(NewCourseActivity.EXTRA_DESCRIPTION);
String courseDuration = data.getStringExtra(NewCourseActivity.EXTRA_DURATION);
CourseModal model = new CourseModal(courseName, courseDescription, courseDuration);
viewmodal.insert(model);
Toast.makeText(this, "Course saved", Toast.LENGTH_SHORT).show();
} else if (requestCode == EDIT_COURSE_REQUEST && resultCode == RESULT_OK) {
int id = data.getIntExtra(NewCourseActivity.EXTRA_ID, -1);
if (id == -1) {
Toast.makeText(this, "Course can't be updated", Toast.LENGTH_SHORT).show();
return;
}
String courseName = data.getStringExtra(NewCourseActivity.EXTRA_COURSE_NAME);
String courseDesc = data.getStringExtra(NewCourseActivity.EXTRA_DESCRIPTION);
String courseDuration = data.getStringExtra(NewCourseActivity.EXTRA_DURATION);
CourseModal model = new CourseModal(courseName, courseDesc, courseDuration);
model.setId(id);
viewmodal.update(model);
Toast.makeText(this, "Course updated", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Course not saved", Toast.LENGTH_SHORT).show();
}
}
}
第4步:创建用于存储数据的模式类
导航到应用程序> Java >应用程序包名称>右键单击它>新建> Java类,并将该类命名为CourseModal,然后将以下代码添加到该类中。在代码内部添加了注释,以更详细地了解代码。
Java
import androidx.room.Entity;
import androidx.room.PrimaryKey;
// below line is for setting table name.
@Entity(tableName = "course_table")
public class CourseModal {
// below line is to auto increment
// id for each course.
@PrimaryKey(autoGenerate = true)
// variable for our id.
private int id;
// below line is a variable
// for course name.
private String courseName;
// below line is use for
// course description.
private String courseDescription;
// below line is use
// for course duration.
private String courseDuration;
// below line we are creating constructor class.
// inside constructor class we are not passing
// our id because it is incrementing automatically
public CourseModal(String courseName, String courseDescription, String courseDuration) {
this.courseName = courseName;
this.courseDescription = courseDescription;
this.courseDuration = courseDuration;
}
// on below line we are creating
// getter and setter methods.
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public String getCourseDescription() {
return courseDescription;
}
public void setCourseDescription(String courseDescription) {
this.courseDescription = courseDescription;
}
public String getCourseDuration() {
return courseDuration;
}
public void setCourseDuration(String courseDuration) {
this.courseDuration = courseDuration;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
步骤5:为我们的数据库创建Dao界面
导航到应用程序> Java >应用程序的包名称>右键单击它>新建> Java类,并将其命名为Dao并选择Interface。创建接口类并将其添加以下代码之后。在代码内部添加了注释,以更详细地了解代码。
Java
import androidx.lifecycle.LiveData;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import java.util.List;
// Adding annotation
// to our Dao class
@androidx.room.Dao
public interface Dao {
// below method is use to
// add data to database.
@Insert
void insert(CourseModal model);
// below method is use to update
// the data in our database.
@Update
void update(CourseModal model);
// below line is use to delete a
// specific course in our database.
@Delete
void delete(CourseModal model);
// on below line we are making query to
// delete all courses from our database.
@Query("DELETE FROM course_table")
void deleteAllCourses();
// below line is to read all the courses from our database.
// in this we are ordering our courses in ascending order
// with our course name.
@Query("SELECT * FROM course_table ORDER BY courseName ASC")
LiveData> getAllCourses();
}
步骤6:创建数据库类
导航到应用程序> Java >应用程序的程序包名称>右键单击它>新建> Java类,并将其命名为CourseDatabase,然后将以下代码添加到其中。在代码内部添加了注释,以更详细地了解代码。
Java
import android.content.Context;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.sqlite.db.SupportSQLiteDatabase;
// adding annotation for our database entities and db version.
@Database(entities = {CourseModal.class}, version = 1)
public abstract class CourseDatabase extends RoomDatabase {
// below line is to create instance
// for our database class.
private static CourseDatabase instance;
// below line is to create
// abstract variable for dao.
public abstract Dao Dao();
// on below line we are getting instance for our database.
public static synchronized CourseDatabase getInstance(Context context) {
// below line is to check if
// the instance is null or not.
if (instance == null) {
// if the instance is null we
// are creating a new instance
instance =
// for creating a instance for our database
// we are creating a database builder and passing
// our database class with our database name.
Room.databaseBuilder(context.getApplicationContext(),
CourseDatabase.class, "course_database")
// below line is use to add fall back to
// destructive migration to our database.
.fallbackToDestructiveMigration()
// below line is to add callback
// to our database.
.addCallback(roomCallback)
// below line is to
// build our database.
.build();
}
// after creating an instance
// we are returning our instance
return instance;
}
// below line is to create a callback for our room database.
private static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
// this method is called when database is created
// and below line is to populate our data.
new PopulateDbAsyncTask(instance).execute();
}
};
// we are creating an async task class to perform task in background.
private static class PopulateDbAsyncTask extends AsyncTask {
PopulateDbAsyncTask(CourseDatabase instance) {
Dao dao = instance.Dao();
}
@Override
protected Void doInBackground(Void... voids) {
return null;
}
}
}
步骤7:为我们的存储库创建一个新的Java类
导航到应用程序> Java >应用程序的程序包名称>右键单击它>新建> Java类,并将其命名为CourseRepository,然后将以下代码添加到其中。在代码内部添加了注释,以更详细地了解代码。
Java
import android.app.Application;
import android.os.AsyncTask;
import androidx.lifecycle.LiveData;
import java.util.List;
public class CourseRepository {
// below line is the create a variable
// for dao and list for all courses.
private Dao dao;
private LiveData> allCourses;
// creating a constructor for our variables
// and passing the variables to it.
public CourseRepository(Application application) {
CourseDatabase database = CourseDatabase.getInstance(application);
dao = database.Dao();
allCourses = dao.getAllCourses();
}
// creating a method to insert the data to our database.
public void insert(CourseModal model) {
new InsertCourseAsyncTask(dao).execute(model);
}
// creating a method to update data in database.
public void update(CourseModal model) {
new UpdateCourseAsyncTask(dao).execute(model);
}
// creating a method to delete the data in our database.
public void delete(CourseModal model) {
new DeleteCourseAsyncTask(dao).execute(model);
}
// below is the method to delete all the courses.
public void deleteAllCourses() {
new DeleteAllCoursesAsyncTask(dao).execute();
}
// below method is to read all the courses.
public LiveData> getAllCourses() {
return allCourses;
}
// we are creating a async task method to insert new course.
private static class InsertCourseAsyncTask extends AsyncTask {
private Dao dao;
private InsertCourseAsyncTask(Dao dao) {
this.dao = dao;
}
@Override
protected Void doInBackground(CourseModal... model) {
// below line is use to insert our modal in dao.
dao.insert(model[0]);
return null;
}
}
// we are creating a async task method to update our course.
private static class UpdateCourseAsyncTask extends AsyncTask {
private Dao dao;
private UpdateCourseAsyncTask(Dao dao) {
this.dao = dao;
}
@Override
protected Void doInBackground(CourseModal... models) {
// below line is use to update
// our modal in dao.
dao.update(models[0]);
return null;
}
}
// we are creating a async task method to delete course.
private static class DeleteCourseAsyncTask extends AsyncTask {
private Dao dao;
private DeleteCourseAsyncTask(Dao dao) {
this.dao = dao;
}
@Override
protected Void doInBackground(CourseModal... models) {
// below line is use to delete
// our course modal in dao.
dao.delete(models[0]);
return null;
}
}
// we are creating a async task method to delete all courses.
private static class DeleteAllCoursesAsyncTask extends AsyncTask {
private Dao dao;
private DeleteAllCoursesAsyncTask(Dao dao) {
this.dao = dao;
}
@Override
protected Void doInBackground(Void... voids) {
// on below line calling method
// to delete all courses.
dao.deleteAllCourses();
return null;
}
}
}
步骤8:为我们的存储库创建一个类
导航到应用程序> Java >应用程序的程序包名称>右键单击它>新建> Java类,并将该类命名为ViewModal,然后将以下代码添加到其中。在代码内部添加了注释,以更详细地了解代码。
Java
import android.app.Application;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import java.util.List;
public class ViewModal extends AndroidViewModel {
// creating a new variable for course repository.
private CourseRepository repository;
// below line is to create a variable for live
// data where all the courses are present.
private LiveData> allCourses;
// constructor for our view modal.
public ViewModal(@NonNull Application application) {
super(application);
repository = new CourseRepository(application);
allCourses = repository.getAllCourses();
}
// below method is use to insert the data to our repository.
public void insert(CourseModal model) {
repository.insert(model);
}
// below line is to update data in our repository.
public void update(CourseModal model) {
repository.update(model);
}
// below line is to delete the data in our repository.
public void delete(CourseModal model) {
repository.delete(model);
}
// below method is to delete all the courses in our list.
public void deleteAllCourses() {
repository.deleteAllCourses();
}
// below method is to get all the courses in our list.
public LiveData> getAllCourses() {
return allCourses;
}
}
步骤9:为RecyclerView的每个项目创建一个布局文件
导航到应用程序> res>布局>右键单击它>新建>布局资源文件,并将其命名为course_rv_item,并在其中添加以下代码。在代码中添加了注释,以便更详细地了解。
XML格式
步骤10:创建RecyclerView Adapter类以为RecyclerView的每个项目设置数据
导航到应用程序> Java >应用程序的程序包名称>右键单击它>新建> Java类,并将其命名为CourseRVAdapter,然后将以下代码添加到其中。在代码内部添加了注释,以更详细地了解代码。
Java
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;
public class CourseRVAdapter extends ListAdapter {
// creating a variable for on item click listener.
private OnItemClickListener listener;
// creating a constructor class for our adapter class.
CourseRVAdapter() {
super(DIFF_CALLBACK);
}
// creating a call back for item of recycler view.
private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() {
@Override
public boolean areItemsTheSame(CourseModal oldItem, CourseModal newItem) {
return oldItem.getId() == newItem.getId();
}
@Override
public boolean areContentsTheSame(CourseModal oldItem, CourseModal newItem) {
// below line is to check the course name, description and course duration.
return oldItem.getCourseName().equals(newItem.getCourseName()) &&
oldItem.getCourseDescription().equals(newItem.getCourseDescription()) &&
oldItem.getCourseDuration().equals(newItem.getCourseDuration());
}
};
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// below line is use to inflate our layout
// file for each item of our recycler view.
View item = LayoutInflater.from(parent.getContext())
.inflate(R.layout.course_rv_item, parent, false);
return new ViewHolder(item);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// below line of code is use to set data to
// each item of our recycler view.
CourseModal model = getCourseAt(position);
holder.courseNameTV.setText(model.getCourseName());
holder.courseDescTV.setText(model.getCourseDescription());
holder.courseDurationTV.setText(model.getCourseDuration());
}
// creating a method to get course modal for a specific position.
public CourseModal getCourseAt(int position) {
return getItem(position);
}
public class ViewHolder extends RecyclerView.ViewHolder {
// view holder class to create a variable for each view.
TextView courseNameTV, courseDescTV, courseDurationTV;
ViewHolder(@NonNull View itemView) {
super(itemView);
// initializing each view of our recycler view.
courseNameTV = itemView.findViewById(R.id.idTVCourseName);
courseDescTV = itemView.findViewById(R.id.idTVCourseDescription);
courseDurationTV = itemView.findViewById(R.id.idTVCourseDuration);
// adding on click listener for each item of recycler view.
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// inside on click listener we are passing
// position to our item of recycler view.
int position = getAdapterPosition();
if (listener != null && position != RecyclerView.NO_POSITION) {
listener.onItemClick(getItem(position));
}
}
});
}
}
public interface OnItemClickListener {
void onItemClick(CourseModal model);
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}
}
步骤11:创建新活动以添加和更新我们的课程
导航到应用程序> Java >您的应用程序的程序包名称>右键单击它>新建>空活动,并将其命名为NewCourseActivity,然后转到XML部分并在其中添加以下代码。以下是activity_new_course.xml文件的代码。
XML格式
步骤12:使用NewCourseActivity。 Java文件
导航到应用程序> Java >您的应用程序的程序包名称> NewCourseActivity。 Java文件,并向其中添加以下代码。在代码内部添加了注释,以更详细地了解代码。
Java
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class NewCourseActivity extends AppCompatActivity {
// creating a variables for our button and edittext.
private EditText courseNameEdt, courseDescEdt, courseDurationEdt;
private Button courseBtn;
// creating a constant string variable for our
// course name, description and duration.
public static final String EXTRA_ID = "com.gtappdevelopers.gfgroomdatabase.EXTRA_ID";
public static final String EXTRA_COURSE_NAME = "com.gtappdevelopers.gfgroomdatabase.EXTRA_COURSE_NAME";
public static final String EXTRA_DESCRIPTION = "com.gtappdevelopers.gfgroomdatabase.EXTRA_COURSE_DESCRIPTION";
public static final String EXTRA_DURATION = "com.gtappdevelopers.gfgroomdatabase.EXTRA_COURSE_DURATION";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_course);
// initializing our variables for each view.
courseNameEdt = findViewById(R.id.idEdtCourseName);
courseDescEdt = findViewById(R.id.idEdtCourseDescription);
courseDurationEdt = findViewById(R.id.idEdtCourseDuration);
courseBtn = findViewById(R.id.idBtnSaveCourse);
// below line is to get intent as we
// are getting data via an intent.
Intent intent = getIntent();
if (intent.hasExtra(EXTRA_ID)) {
// if we get id for our data then we are
// setting values to our edit text fields.
courseNameEdt.setText(intent.getStringExtra(EXTRA_COURSE_NAME));
courseDescEdt.setText(intent.getStringExtra(EXTRA_DESCRIPTION));
courseDurationEdt.setText(intent.getStringExtra(EXTRA_DURATION));
}
// adding on click listener for our save button.
courseBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// getting text value from edittext and validating if
// the text fields are empty or not.
String courseName = courseNameEdt.getText().toString();
String courseDesc = courseDescEdt.getText().toString();
String courseDuration = courseDurationEdt.getText().toString();
if (courseName.isEmpty() || courseDesc.isEmpty() || courseDuration.isEmpty()) {
Toast.makeText(NewCourseActivity.this, "Please enter the valid course details.", Toast.LENGTH_SHORT).show();
return;
}
// calling a method to save our course.
saveCourse(courseName, courseDesc, courseDuration);
}
});
}
private void saveCourse(String courseName, String courseDescription, String courseDuration) {
// inside this method we are passing
// all the data via an intent.
Intent data = new Intent();
// in below line we are passing all our course detail.
data.putExtra(EXTRA_COURSE_NAME, courseName);
data.putExtra(EXTRA_DESCRIPTION, courseDescription);
data.putExtra(EXTRA_DURATION, courseDuration);
int id = getIntent().getIntExtra(EXTRA_ID, -1);
if (id != -1) {
// in below line we are passing our id.
data.putExtra(EXTRA_ID, id);
}
// at last we are setting result as data.
setResult(RESULT_OK, data);
// displaying a toast message after adding the data
Toast.makeText(this, "Course has been saved to Room Database. ", Toast.LENGTH_SHORT).show();
}
}
步骤13:使用MainActivity。 Java文件
导航到应用程序> Java >您的应用程序的程序包名称> MainActivity。 Java文件,并向其中添加以下代码。在代码内部添加了注释,以更详细地了解代码。
Java
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.List;
public class MainActivity extends AppCompatActivity {
// creating a variables for our recycler view.
private RecyclerView coursesRV;
private static final int ADD_COURSE_REQUEST = 1;
private static final int EDIT_COURSE_REQUEST = 2;
private ViewModal viewmodal;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initializing our variable for our recycler view and fab.
coursesRV = findViewById(R.id.idRVCourses);
FloatingActionButton fab = findViewById(R.id.idFABAdd);
// adding on click listener for floating action button.
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// starting a new activity for adding a new course
// and passing a constant value in it.
Intent intent = new Intent(MainActivity.this, NewCourseActivity.class);
startActivityForResult(intent, ADD_COURSE_REQUEST);
}
});
// setting layout manager to our adapter class.
coursesRV.setLayoutManager(new LinearLayoutManager(this));
coursesRV.setHasFixedSize(true);
// initializing adapter for recycler view.
final CourseRVAdapter adapter = new CourseRVAdapter();
// setting adapter class for recycler view.
coursesRV.setAdapter(adapter);
// passing a data from view modal.
viewmodal = ViewModelProviders.of(this).get(ViewModal.class);
// below line is use to get all the courses from view modal.
viewmodal.getAllCourses().observe(this, new Observer>() {
@Override
public void onChanged(List models) {
// when the data is changed in our models we are
// adding that list to our adapter class.
adapter.submitList(models);
}
});
// below method is use to add swipe to delete method for item of recycler view.
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
// on recycler view item swiped then we are deleting the item of our recycler view.
viewmodal.delete(adapter.getCourseAt(viewHolder.getAdapterPosition()));
Toast.makeText(MainActivity.this, "Course deleted", Toast.LENGTH_SHORT).show();
}
}).
// below line is use to attach this to recycler view.
attachToRecyclerView(coursesRV);
// below line is use to set item click listener for our item of recycler view.
adapter.setOnItemClickListener(new CourseRVAdapter.OnItemClickListener() {
@Override
public void onItemClick(CourseModal model) {
// after clicking on item of recycler view
// we are opening a new activity and passing
// a data to our activity.
Intent intent = new Intent(MainActivity.this, NewCourseActivity.class);
intent.putExtra(NewCourseActivity.EXTRA_ID, model.getId());
intent.putExtra(NewCourseActivity.EXTRA_COURSE_NAME, model.getCourseName());
intent.putExtra(NewCourseActivity.EXTRA_DESCRIPTION, model.getCourseDescription());
intent.putExtra(NewCourseActivity.EXTRA_DURATION, model.getCourseDuration());
// below line is to start a new activity and
// adding a edit course constant.
startActivityForResult(intent, EDIT_COURSE_REQUEST);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ADD_COURSE_REQUEST && resultCode == RESULT_OK) {
String courseName = data.getStringExtra(NewCourseActivity.EXTRA_COURSE_NAME);
String courseDescription = data.getStringExtra(NewCourseActivity.EXTRA_DESCRIPTION);
String courseDuration = data.getStringExtra(NewCourseActivity.EXTRA_DURATION);
CourseModal model = new CourseModal(courseName, courseDescription, courseDuration);
viewmodal.insert(model);
Toast.makeText(this, "Course saved", Toast.LENGTH_SHORT).show();
} else if (requestCode == EDIT_COURSE_REQUEST && resultCode == RESULT_OK) {
int id = data.getIntExtra(NewCourseActivity.EXTRA_ID, -1);
if (id == -1) {
Toast.makeText(this, "Course can't be updated", Toast.LENGTH_SHORT).show();
return;
}
String courseName = data.getStringExtra(NewCourseActivity.EXTRA_COURSE_NAME);
String courseDesc = data.getStringExtra(NewCourseActivity.EXTRA_DESCRIPTION);
String courseDuration = data.getStringExtra(NewCourseActivity.EXTRA_DURATION);
CourseModal model = new CourseModal(courseName, courseDesc, courseDuration);
model.setId(id);
viewmodal.update(model);
Toast.makeText(this, "Course updated", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Course not saved", Toast.LENGTH_SHORT).show();
}
}
}
现在运行您的应用程序,并查看该应用程序的输出。
输出:
在以下链接上查看项目: https : //github.com/ChaitanyaMunje/GFG-Room-Database