Android SQLite - RecyclerView - CRUD then Swipe To Delete Data


Android SQLite RecyclerView - CRUD then Swipe To Delete Data Tutorial.

We want to see how we can implement a ItemTouchHelper with a RecyclerView filled from SQLite database.

Thus if the user swipes away a RecyclerView item, that item is deleted automatically from the database.

But first we see how to insert into mysql database , then retrieve that data and show in a RecyclerView. Then user can delete by swiping away.

Our mission at ProgrammingWizards Youtube Channel  is to provide practical realworld examples.There is alot of theory on the web.But then its always easier to learn by doing.So we aim to fill that gap by providing quality examples,that you can easily extend and use in your app. Today we talk about Swipe To Delete,of course from Swipe to Dismiss.We use ItemTouchHelper class,no third party library.We shall do these:

  •  INSERT,SELECT and DELETE to and from SQLite database.
  • To delete we shall use the Swipe to dismiss technique,in this case swipe to delete from database.
  • We then refresh our adapter for instant change notifications.

RecyclerView Swipe To Delete

SQLite Swipe Delete Project Structure

1. Create Basic Activity Project

Let's start by creating a basic project in android studio. You can see how to do so here.

2. Add Gradle Dependencies

We add support library dependencies via the build.gradle.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.android.support:design:23.3.0'
    compile 'com.android.support:cardview-v7:23.3.0'

}

4. Java Classes

Here are our java classes:

Our data object

(a). Planet.java

This is our POJO class. Also called our bean class or our data object. Every row in our database will comprise of this class's object.

It represents a single planet with name and id.

package com.tutorials.hp.sqliteswipetodelete.mDataObject;

public class Planet {

    String name;
    int id;

    public Planet() {
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

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

Our SQLite Classes

(a). Constants.java

This Constants class will contain or hold our SQLite database constants.

These include SQLite table Column names, database name, table name, database verions, SQLite table creation statement and sqlite table dropping statement.

We just define them as string constants using the static final modifier.

package com.tutorials.hp.sqliteswipetodelete.mDataBase;

public class Constants {

    //COLUMNS
    static final String ROW_ID="id";
    static final String NAME="name";

    //DB PROPS
    static final String DB_NAME="ee_DB";
    static final String TB_NAME="ee_TB";
    static final int DB_VERSION=1;

    //CREATE TABLE
    static final String CREATE_TB="CREATE TABLE ee_TB(id INTEGER PRIMARY KEY AUTOINCREMENT,"
            + "name TEXT NOT NULL);";

    //DROP TB
    static final String DROP_TB="DRP TABLE IF EXISTS "+TB_NAME;

}
(b). DBHelper.java

Our SQLiteOpenHelper class.

To help us create the SQLite table and drop it as well. We start by making it extend the SQLiteOpenHelper class. Then we define one public constructor which will take a Context object.

We will override the onCreate() and the onUpgrade() methods. The database table will be created and updated in the two methods respectively.

package com.tutorials.hp.sqliteswipetodelete.mDataBase;

import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DBHelper extends SQLiteOpenHelper {
    public DBHelper(Context context) {
        super(context, Constants.DB_NAME, null, Constants.DB_VERSION);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        try {
            db.execSQL(Constants.CREATE_TB);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(Constants.DROP_TB);
        onCreate(db);
    }
}
(c). DBAdapter.java

This is our CRUD class. It is where we perform our SQLite CRUD operations.

Here we will open database connection, then save our data to sqlite, select them and close our connection.

Basically all our CRUD SQLite operations,inserting data,selecting and updating we do inside this class :  

package com.tutorials.hp.sqliteswipetodelete.mDataBase;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class DBAdapter {

    Context c;
    SQLiteDatabase db;
    DBHelper helper;

    public DBAdapter(Context c) {
        this.c = c;
        helper=new DBHelper(c);
    }

    //OPEN DB
    public void openDB()
    {
        try {
            db=helper.getWritableDatabase();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //CLOSE DB
    public void closeDB()
    {
        try {
           helper.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //INSERT/SAVE
    public boolean add(String name)
    {
        try {
        ContentValues cv=new ContentValues();
        cv.put(Constants.NAME, name);

         db.insert(Constants.TB_NAME, Constants.ROW_ID, cv);
        return true;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    //SELECT/RETRIEVE
    public Cursor retrieve()
    {
        String[] columns={Constants.ROW_ID,Constants.NAME};

        return db.query(Constants.TB_NAME,columns,null,null,null,null,null);
    }

    //DELETE/REMOVE
    public boolean delete(int id)
    {
        try {
            int result=db.delete(Constants.TB_NAME,Constants.ROW_ID+" =?",new String[]{String.valueOf(id)});
            if(result>0) {
                return true;
            }

          } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

}

Our ItemTouchHelper Class

(a). SwipeHelper.java

This is our ItemTouchHelper.SimpleCallback class.

 We are creating a swipe helper class that's going to derive from ItemTouchHelper.SimpleCallback.Its going to take our Adapter reference and invoke the method for deleting data inside the onSwiped method :

This class will allow us delete a planet from our RecyclerView when user swipes that item in the RecyclerView.

package com.tutorials.hp.sqliteswipetodelete.mSwiper;

import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;

import com.tutorials.hp.sqliteswipetodelete.mRecycler.MyAdapter;

public class SwipeHelper extends ItemTouchHelper.SimpleCallback {

   MyAdapter adapter;

    public SwipeHelper(int dragDirs, int swipeDirs) {
        super(dragDirs, swipeDirs);
    }

    public SwipeHelper( MyAdapter adapter) {
        super(ItemTouchHelper.UP | ItemTouchHelper.DOWN,ItemTouchHelper.LEFT);
        this.adapter = adapter;
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        return false;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
         adapter.deletePlanet(viewHolder.getAdapterPosition());
    }
}

Our RecyclerView Classes

(a). MyHolder.java

Our RecyclerView ViewHolder class. Will simply hold our TextView for recycling.

package com.tutorials.hp.sqliteswipetodelete.mRecycler;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;

import com.tutorials.hp.sqliteswipetodelete.R;

public class MyHolder extends RecyclerView.ViewHolder {

    TextView nametxt;

    public MyHolder(View itemView) {
        super(itemView);

        this.nametxt= (TextView) itemView.findViewById(R.id.nameTxt);
    }
}

SQLite Swipe To Delete Insert Data Material Dialog

(b). MyAdapter.java

Our RecyclerView Adapter class. It has to extend the RecyclerView.Adapter<MyHolder> class. The MyHolder generic parameter is our Recyclreview ViewHolder class.

Our RecyclerView shall have this adapter class so that it binds our data to inflated views. That inflation will also take place here.

Our constructor will take a context and an arraylist of planet objects. Those planet objects are what will populate our Recyclerview. The Context object shall be needed for inflation of the model.xml layout to occur.

package com.tutorials.hp.sqliteswipetodelete.mRecycler;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.tutorials.hp.sqliteswipetodelete.R;
import com.tutorials.hp.sqliteswipetodelete.mDataBase.DBAdapter;
import com.tutorials.hp.sqliteswipetodelete.mDataObject.Planet;

import java.util.ArrayList;

public class MyAdapter extends RecyclerView.Adapter<MyHolder> {

    Context c;
    ArrayList<Planet> planets;

    public MyAdapter(Context c, ArrayList<Planet> planets) {
        this.c = c;
        this.planets = planets;
    }

    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.model,parent,false);
        MyHolder holder=new MyHolder(v);
        return holder;
    }

    @Override
    public void onBindViewHolder(MyHolder holder, int position) {
         holder.nametxt.setText(planets.get(position).getName());
    }

    @Override
    public int getItemCount() {
        return planets.size();
    }

    public void deletePlanet(int pos)
    {
        //GET ID
        Planet p=planets.get(pos);
        int id=p.getId();

        //DELETE FROM DB
        DBAdapter db=new DBAdapter(c);
        db.openDB();
        if(db.delete(id))
        {
            planets.remove(pos);
        }else
        {
            Toast.makeText(c,"Unable To Delete",Toast.LENGTH_SHORT).show();
        }

        db.closeDB();

        this.notifyItemRemoved(pos);

    }
}

Our Activity Class

(a). MainActivity.java

Our MainActivity class. This class represents our user interface. This is where we will render our user interface widgets like RecyclerView. We will also be able to show an input dialog. That is the dialog used to type data that should be saved in sqlite database. So that dialog also in fact gets hosted by this activity.

package com.tutorials.hp.sqliteswipetodelete;

import android.app.Dialog;
import android.database.Cursor;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.tutorials.hp.sqliteswipetodelete.mDataBase.DBAdapter;
import com.tutorials.hp.sqliteswipetodelete.mDataObject.Planet;
import com.tutorials.hp.sqliteswipetodelete.mRecycler.MyAdapter;
import com.tutorials.hp.sqliteswipetodelete.mSwiper.SwipeHelper;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    RecyclerView rv;
    MyAdapter adapter;
    EditText nameEditText;
    Button saveBtn,retrieveBtn;
    ArrayList<Planet> planets=new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);

        rv= (RecyclerView) findViewById(R.id.rv);
        rv.setLayoutManager(new LinearLayoutManager(this));

        adapter=new MyAdapter(this,planets);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                displayDialog();
            }
        });

        ItemTouchHelper.Callback callback=new SwipeHelper(adapter);
        ItemTouchHelper helper=new ItemTouchHelper(callback);
        helper.attachToRecyclerView(rv);

    }

    private void displayDialog()
    {
        Dialog d=new Dialog(this);
        d.setTitle("SQLite database");
        d.setContentView(R.layout.dialog_layout);

        nameEditText= (EditText) d.findViewById(R.id.nameEditTxt);
        saveBtn= (Button) d.findViewById(R.id.saveBtn);
        retrieveBtn= (Button) d.findViewById(R.id.retrieveBtn);

        saveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                 save(nameEditText.getText().toString());
            }
        });

        retrieveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getPlanets();
            }
        });

        //SHOW DIALOG
        d.show();

    }

    //SAVE
    private void save(String name)
    {
        DBAdapter db=new DBAdapter(this);
        db.openDB();
        if(db.add(name))
        {
            nameEditText.setText("");
        }else
        {
            Toast.makeText(this,"Unable to save",Toast.LENGTH_SHORT).show();
        }

        db.closeDB();
    }

    //RETRIEVE
    private void getPlanets()
    {
        planets.clear();

        DBAdapter db=new DBAdapter(this);
        db.openDB();
        Cursor c=db.retrieve();

        while (c.moveToNext())
        {
            int id=c.getInt(0);
            String name=c.getString(1);

            Planet p=new Planet();
            p.setName(name);
            p.setId(id);

            planets.add(p);
        }
        db.closeDB();

        if(planets.size()>0)
        {
            rv.setAdapter(adapter);
        }
    }

}

Download

Download code below.

If you prefer more explanations or want to see the demo then the video tutorial is here.

No. Location Link
1. GitHub Direct Download)
2. GitHub Browse
3. YouTube Video Tutorial
4. YouTube Our YouTube Channel

How do You Feel after reading this?

According to scientists, we humans have 8 primary innate emotions: joy, acceptance, fear, surprise, sadness, disgust, anger, and anticipation. Feel free to tell us how you feel about this article using these emotes or via the comment section. This feedback helps us gauge our progress.

Help me Grow.

I set myself some growth ambitions I desire to achieve by this year's end regarding this website and my youtube channel. Am halfway. Help me reach them by:




Recommendations


What do You Think


Previous Post Next Post