RecyclerView CRUD operation with image picks from camera or gallery and store in SQLite database
We will create an awesome UI Design RecyclerView CRUD operation in Android Studio. We will perform a CRUD operation using the SQLite database that you already know.
In the previous tutorial we saw RecyclerView CRUD (Create, Read, Update, Delete) operation using SQLite database. We entered the user’s first and last name and using an adapter, we displayed the data in the Recyclerview, then perform an updated and deleted operation.
So guys in this tutorial, we will do RecycleView CRUD operation using SQLite database in Android Studio. This CRUD operation is different as a unique UI design and image is being used here. Meaning you can pick image from camera or gallery and store in SQLite database. We will use some external libraries to make it work smoothly without any errors.
It is very important to know about tutorials before starting an example.
What includes in these tutorials?
- Simple, we did the same as we did in the previous tutorial. You know, first, we create a database helper class to store the data and version management.
- After that an activity will be created for inserted data, main activity is given by default, so using the default activity we will insert data into the SQLite database.
- Then we will create a model class to store the data. Then we will create adapter class to display data in RecyclerView and create a single data xml file for singleview.
- After that, we will create DisplayData Activity to display items in RecyclerView using Adapter class.
Let us understand with example.
Step:-1 Database class
You know that first we create a database class for management, creation and version management and extends SQLiteOpenHelper and then implement the subclass. You already know about this.
Create a Java class named DBmain.
App⇾java ⇾right click on package name⇾new ⇾java class.
The code of DBmain.java is given below
DBmain.java
package com.example.recyclerviewwithimage;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
public class DBmain extends SQLiteOpenHelper {
public static final String DBNAME = "student.db";
public static final String TABLENAME = "course";
public static final int VER = 1;
public DBmain(@Nullable Context context) {
super(context, DBNAME, null, VER);
}
@Override
public void onCreate(SQLiteDatabase db) {
String query = "create table " + TABLENAME + "(id integer primary key, avatar blob, name text)";
db.execSQL(query);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String query = "drop table if exists " + TABLENAME + "";
db.execSQL(query);
}
}
Step:-2 activity_main.xml
Through this main xml file we will enter the data for the insertion operation. Start this activity. Through this activity, we would add EditText and Button.
Normally this is the default activity, automatically created the main activity when you create the project.
You can find it inside the layout. App->layout->activity_main.xml.
The code of activity_main.xml is given below
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".MainActivity">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:id="@+id/avatar"
android:src="@mipmap/ic_launcher"
android:layout_centerHorizontal="true"/>
<EditText
android:layout_below="@+id/avatar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/edit_name"
android:hint="Name"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/edit_name"
android:id="@+id/btn_submit"
android:text="Submit"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/edit_name"
android:id="@+id/btn_edit"
android:text="Edit"
android:visibility="gone"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_display"
android:text="Display"
android:layout_alignParentRight="true"
android:layout_below="@+id/edit_name"/>
</RelativeLayout>
Step :-3 dependences
Before starting the MainActvity.java activity, we need some dependencies. We’ll use images, so we needed crop image functionality, so we will add some external dependencies.
Go to ->gradle Scripts ->build. Gradle and add below dependencies.
//crop image
api'com.theartofdev.edmodo:android-image-cropper:2.8.0'
//loading image in imageview
implementation'com.squareup.picasso:picasso:2.5.2'
And add some permission on AndroidManifest
The code of AndroidManifest file is given below.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.recyclerviewwithimage">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.RecyclerviewwithImage">
<activity android:name=".DisplayData"></activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.theartofdev.edmodo.cropper.CropImageActivity" />
</application>
</manifest>
Step :-4 MainActvity.java
In the MainActvity.java activity, we’ll perform an insertion operation.
Inside MainActivity.java we’ll also perform pick image from camera or gallery and display in imageview. And will edit user data and as well as display data.
The code of MainActivity.java is given below.
MainActivity.java
package com.example.recyclerviewwithimage;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import com.squareup.picasso.Picasso;
import com.theartofdev.edmodo.cropper.CropImage;
import java.io.ByteArrayOutputStream;
import static com.example.recyclerviewwithimage.DBmain.TABLENAME;
public class MainActivity extends AppCompatActivity {
DBmain dBmain;
SQLiteDatabase sqLiteDatabase;
ImageView avatar;
EditText name;
Button submit,display,edit;
int id=0;
public static final int CAMERA_REQUEST=100;
public static final int STORAGE_REQUEST=101;
String[]cameraPermission;
String[]storagePermission;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dBmain=new DBmain(this);
findid();
insertData();
imagePick();
editData();
}
private void editData() {
if (getIntent().getBundleExtra("userdata")!=null){
Bundle bundle=getIntent().getBundleExtra("userdata");
id=bundle.getInt("id");
//for image
byte[]bytes=bundle.getByteArray("avatar");
Bitmap bitmap=BitmapFactory.decodeByteArray(bytes,0,bytes.length);
avatar.setImageBitmap(bitmap);
//for set name
name.setText(bundle.getString("name"));
//visible edit button and hide submit button
submit.setVisibility(View.GONE);
edit.setVisibility(View.VISIBLE);
}
}
private void imagePick() {
avatar.setOnClickListener(new View.OnClickListener() {
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onClick(View v) {
int avatar=0;
if (avatar==0){
if (!checkCameraPermission()){
requestCameraPermission();
}else {
pickFromGallery();
}
}else if (avatar==1){
if (!checkStoragePermission()){
requestStoragePermission();
}else{
pickFromGallery();
}
}
}
});
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void requestStoragePermission() {
requestPermissions(storagePermission,STORAGE_REQUEST);
}
private boolean checkStoragePermission() {
boolean result=ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)==(PackageManager.PERMISSION_GRANTED);
return result;
}
private void pickFromGallery() {
CropImage.activity().start(this);
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void requestCameraPermission() {
requestPermissions(cameraPermission,CAMERA_REQUEST);
}
private boolean checkCameraPermission() {
boolean result= ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)==(PackageManager.PERMISSION_GRANTED);
boolean result2=ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA)==(PackageManager.PERMISSION_GRANTED);
return result && result2;
}
private void insertData() {
submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ContentValues cv=new ContentValues();
cv.put("avatar",ImageViewToByte(avatar));
cv.put("name",name.getText().toString());
sqLiteDatabase=dBmain.getWritableDatabase();
Long recinsert=sqLiteDatabase.insert(TABLENAME,null,cv);
if (recinsert!=null){
Toast.makeText(MainActivity.this, "inserted successfully", Toast.LENGTH_SHORT).show();
//clear when click on submit button
avatar.setImageResource(R.mipmap.ic_launcher);
name.setText("");
}
}
});
display.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,DisplayData.class));
}
});
//for storing new data or update data
edit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ContentValues cv=new ContentValues();
cv.put("avatar",ImageViewToByte(avatar));
cv.put("name",name.getText().toString());
sqLiteDatabase=dBmain.getWritableDatabase();
long recedit=sqLiteDatabase.update(TABLENAME,cv,"id="+id,null);
if (recedit!=-1){
Toast.makeText(MainActivity.this, "Update successfully", Toast.LENGTH_SHORT).show();
//clear data after submit
avatar.setImageResource(R.mipmap.ic_launcher);
name.setText("");
//edit hide and submit visible
edit.setVisibility(View.GONE);
submit.setVisibility(View.VISIBLE);
}
}
});
}
private byte[] ImageViewToByte(ImageView avatar) {
Bitmap bitmap=((BitmapDrawable)avatar.getDrawable()).getBitmap();
ByteArrayOutputStream stream=new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG,80,stream);
byte[]bytes=stream.toByteArray();
return bytes;
}
private void findid() {
avatar=(ImageView)findViewById(R.id.avatar);
name=(EditText)findViewById(R.id.edit_name);
submit=(Button)findViewById(R.id.btn_submit);
display=(Button)findViewById(R.id.btn_display);
edit=(Button)findViewById(R.id.btn_edit);
}
//overrid method onRequestPermissionResult
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case CAMERA_REQUEST:{
if (grantResults.length>0){
boolean camera_accept=grantResults[0]==PackageManager.PERMISSION_GRANTED;
boolean storage_accept=grantResults[1]==PackageManager.PERMISSION_GRANTED;
if (camera_accept&&storage_accept){
pickFromGallery();
}else{
Toast.makeText(this, "enable camera and storage permission", Toast.LENGTH_SHORT).show();
}
}
}
break;
case STORAGE_REQUEST:{
if (grantResults.length>0){
boolean storage_accept=grantResults[0]==PackageManager.PERMISSION_GRANTED;
if (storage_accept){
pickFromGallery();
}else{
Toast.makeText(this, "please enable storage permission", Toast.LENGTH_SHORT).show();
}
}
}
break;
}
}
//overrid method
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE){
CropImage.ActivityResult result=CropImage.getActivityResult(data);
if (resultCode==RESULT_OK){
Uri resultUri=result.getUri();
Picasso.with(this).load(resultUri).into(avatar);
}
}
}
}
Our insertion operation is completed. Now, here you can insert data into the SQLite database.
Step:- 5 Model class
Friends now create a “Model class” to store the data and generate constructor and getter and setter methods.
App⇾java ⇾right click on package name ⇾new ⇾java class.
The code of Model class is given below.
Model.java
package com.example.recyclerviewwithimage;
public class Model{
private int id;
private byte[]proavatar;
private String username;
//constructor
public Model(int id, byte[] proavatar, String username) {
this.id = id;
this.proavatar = proavatar;
this.username = username;
}
//getter and setter method
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public byte[] getProavatar() {
return proavatar;
}
public void setProavatar(byte[] proavatar) {
this.proavatar = proavatar;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
Step:- 6 Adapter
Create an adapter class named MyAdapter.
App ⇾ java ⇾right click on package name ⇾ new ⇾ java class.
Inside MyAdapter we will also use the popup menu to show edit and delete options display as a popup.
See as below the popup menu code.
holder.flowmenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PopupMenu popupMenu=new PopupMenu(context,holder.flowmenu);
popupMenu.inflate(R.menu.flow_menu);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.edit_menu:
///////
//edit operation
Bundle bundle=new Bundle();
bundle.putInt("id",model.getId());
bundle.putByteArray("avatar",model.getProavatar());
bundle.putString("name",model.getUsername());
Intent intent=new Intent(context,MainActivity.class);
intent.putExtra("userdata",bundle);
context.startActivity(intent);
break;
case R.id.delete_menu:
///delete operation
DBmain dBmain=new DBmain(context);
sqLiteDatabase=dBmain.getReadableDatabase();
long recdelete=sqLiteDatabase.delete(TABLENAME,"id="+model.getId(),null);
if (recdelete!=-1){
Toast.makeText(context, "data deleted", Toast.LENGTH_SHORT).show();
//remove position after deleted
modelArrayList.remove(position);
//update data
notifyDataSetChanged();
}
break;
default:
return false;
}
return false;
}
});
//display menu
popupMenu.show();
}
});
Before creating a popup menu, we need a menu in the Android resource directory.
app ⇾right click on res ⇾new ⇾Android Resource Directory. Then right click on menu⇾new ⇾ Menu Resource File.
In Menu Resource File, add the below code.
flow_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="Edit"
android:id="@+id/edit_menu"/>
<item android:title="Delete"
android:id="@+id/delete_menu"/>
</menu>
Extends RecyclerView.Adapter<MyAdapter.ViewHolder> and implement all required subclass.
The code of MyAdapter is given below
MyAdapter.java
package com.example.recyclerviewwithimage;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.lang.reflect.Array;
import java.util.ArrayList;
import static com.example.recyclerviewwithimage.DBmain.TABLENAME;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
Context context;
int singledata;
ArrayList<Model>modelArrayList;
SQLiteDatabase sqLiteDatabase;
//generate constructor
public MyAdapter(Context context, int singledata, ArrayList<Model> modelArrayList, SQLiteDatabase sqLiteDatabase) {
this.context = context;
this.singledata = singledata;
this.modelArrayList = modelArrayList;
this.sqLiteDatabase = sqLiteDatabase;
}
@NonNull
@Override
public MyAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater=LayoutInflater.from(context);
View view=inflater.inflate(R.layout.singledata,null);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MyAdapter.ViewHolder holder, int position) {
final Model model=modelArrayList.get(position);
byte[]image=model.getProavatar();
Bitmap bitmap= BitmapFactory.decodeByteArray(image,0,image.length);
holder.imageavatar.setImageBitmap(bitmap);
holder.txtname.setText(model.getUsername());
//flow menu
holder.flowmenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PopupMenu popupMenu=new PopupMenu(context,holder.flowmenu);
popupMenu.inflate(R.menu.flow_menu);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.edit_menu:
///////
//edit operation
Bundle bundle=new Bundle();
bundle.putInt("id",model.getId());
bundle.putByteArray("avatar",model.getProavatar());
bundle.putString("name",model.getUsername());
Intent intent=new Intent(context,MainActivity.class);
intent.putExtra("userdata",bundle);
context.startActivity(intent);
break;
case R.id.delete_menu:
///delete operation
DBmain dBmain=new DBmain(context);
sqLiteDatabase=dBmain.getReadableDatabase();
long recdelete=sqLiteDatabase.delete(TABLENAME,"id="+model.getId(),null);
if (recdelete!=-1){
Toast.makeText(context, "data deleted", Toast.LENGTH_SHORT).show();
//remove position after deleted
modelArrayList.remove(position);
//update data
notifyDataSetChanged();
}
break;
default:
return false;
}
return false;
}
});
//display menu
popupMenu.show();
}
});
}
@Override
public int getItemCount() {
return modelArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageavatar;
TextView txtname;
ImageButton flowmenu;
public ViewHolder(@NonNull View itemView) {
super(itemView);
imageavatar=(ImageView)itemView.findViewById(R.id.viewavatar);
txtname=(TextView)itemView.findViewById(R.id.txt_name);
flowmenu=(ImageButton)itemView.findViewById(R.id.flowmenu);
}
}
}
Step:-7 single data view
Now, create a single view data view file in xml
App⇾ res ⇾ right click layout ⇾ new ⇾Layout Resource File named singledata.xml.
The code of singledata.xml is given below
Singeldata.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardElevation="2dp"
app:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true"
app:cardCornerRadius="8dp">
<RelativeLayout
android:background="@drawable/border"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:background="@null"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/flowmenu"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:src="@drawable/ic_baseline_more_vert_24"/>
<ImageView
android:scaleType="fitXY"
android:layout_width="50dp"
android:layout_height="50dp"
android:paddingLeft="5dp"
android:id="@+id/viewavatar"
android:src="@drawable/ic_launcher_background"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/viewavatar"
android:text="@string/app_name"
android:layout_marginTop="10dp"
android:id="@+id/txt_name"
android:layout_marginLeft="20dp"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
Step:-8 activity_display_data.xml
Now, we’ll create a new display data activity.
App⇾java ⇾right click on package name⇾new ⇾activity ⇾ empty activity Named DisplayData.
Open activity_display_data.xml and add recyclerview widget.
The code of activity_display_data.xml is given below
activity_display_data.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:background="#DFD0CC"
tools:context=".DisplayData">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rv"/>
</RelativeLayout>
Step:-9 DisplayData.java
Go to DisplayData.java and add the below code inside DisplayData.java.
DisplayData.java
package com.example.recyclerviewwithimage;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.LayoutInflater;
import java.util.ArrayList;
import static com.example.recyclerviewwithimage.DBmain.TABLENAME;
public class DisplayData extends AppCompatActivity {
DBmain dBmain;
SQLiteDatabase sqLiteDatabase;
RecyclerView recyclerView;
MyAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_data);
dBmain=new DBmain(this);
findId();
displayData();
recyclerView.setLayoutManager(new LinearLayoutManager(this,RecyclerView.VERTICAL,false));
}
private void displayData() {
sqLiteDatabase=dBmain.getReadableDatabase();
Cursor cursor=sqLiteDatabase.rawQuery("select *from "+TABLENAME+"",null);
ArrayList<Model>models=new ArrayList<>();
while (cursor.moveToNext()){
int id=cursor.getInt(0);
byte[]avatar=cursor.getBlob(1);
String name=cursor.getString(2);
models.add(new Model(id,avatar,name));
}
cursor.close();
myAdapter=new MyAdapter(this,R.layout.singledata,models,sqLiteDatabase);
recyclerView.setAdapter(myAdapter);
}
private void findId() {
recyclerView=findViewById(R.id.rv);
}
}
Congrats, your project is ready. Now run your project and see the output.