Managing SQLite database with ORMLite in Android

    SQLite is the only relational database management system was supported in popular Mobile OS platforms. Android provides full support for SQLite databases. Any databases you create will be accessible by name to any class in the application, but not outside the application. With creating a subclass of SQLiteOpenHelper, we can initialize a database from simple to complicate in our app. But by this "classic way", it's will very hard in coding and deploying, so we should use a "short cut" to create and manage the database by use an external libary.
    The most powerful library in this case is ORMLite. It provides some simple, lightweight functionality for persisting Java objects to SQL databases while avoiding the complexity and overhead of more standard ORM packages. Moreover, it also solved well the problems concerning the relationship between the entities/tables.
    Today, in this post, I would like to build a simple project which creating/managing a database with ORMLite, resolved entities relationships by ForeignCollection object. See this DEMO VIDEO for output:

Before Start

    Project description:
- I have 2 POJOs: Cat and Kitten. ORMLite will persist theme to 2 corresponding tables.
- Relationship: Cat : Kitten = 1 : n.
    Adding dependencies to app/build.gradle befor start coding:
    compile 'com.j256.ormlite:ormlite-core:4.48'
    compile 'com.j256.ormlite:ormlite-android:4.48'
- Project structure:

Creating Database/Tables

    As note above, ORMLite persists Java objects to database tables. Through @DatabaseField annotation, each POJO property will be persist to each table field. In this 2 models, the 1:n relationships were resolved by using ForeignCollection:
package info.devexchanges.ormlite.model;

import com.j256.ormlite.dao.ForeignCollection;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.field.ForeignCollectionField;

import java.util.ArrayList;
import java.util.List;

public class Cat {
    @DatabaseField(generatedId=true)
    private int id;

    @DatabaseField (columnName = "name")
    private String name;

    @ForeignCollectionField
    private ForeignCollection<Kitten> kittens;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public void setKittens(ForeignCollection<Kitten> items) {
        this.kittens = items;
    }

    public List<Kitten> getKittens() {
        ArrayList<Kitten> itemList = new ArrayList<>();
        for (Kitten item : kittens) {
            itemList.add(item);
        }
        return itemList;
    }

    @Override
    public String toString() {
        return this.name;
    }
}
package info.devexchanges.ormlite.model;

import com.j256.ormlite.field.DatabaseField;

public class Kitten {

    @DatabaseField(generatedId=true)
    private int id;

    @DatabaseField (columnName = "name")
    private String name;

    @DatabaseField(foreign=true, foreignAutoRefresh=true)
    private Cat cat;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }
}

Building Database Helper and Controller classes

    Like the "original way", we also create a subclass of ORMLiteOpenHelper to initializing database. In this, we can get all tables records to DAO objects (the definition of the Database Access Objects that handle the reading and writing a class from the database), display/update/delete Cat or Kitten also through it's DAO:
package info.devexchanges.ormlite.database;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;

import info.devexchanges.ormlite.model.Cat;
import info.devexchanges.ormlite.model.Kitten;

public class DatabaseHelper extends OrmLiteSqliteOpenHelper {

    // name of the database file for your application -- change to something appropriate for your app
    private static final String DATABASE_NAME = "cat.db";

    // any time you make changes to your database objects, you may have to increase the database version
    private static final int DATABASE_VERSION = 1;

    // the DAO object we use to access the SimpleData table
    private Dao<Cat, Integer> catDAO = null;
    private Dao<Kitten, Integer> kittenDAO = null;

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
        try {
            TableUtils.createTable(connectionSource, Cat.class);
            TableUtils.createTable(connectionSource, Kitten.class);

        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (java.sql.SQLException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) {
        try {
            List<String> allSql = new ArrayList<>();
            for (String sql : allSql) {
                db.execSQL(sql);
            }
        } catch (SQLException e) {
            Log.e(DatabaseHelper.class.getName(), "exception during onUpgrade", e);
            throw new RuntimeException(e);
        }

    }

    public Dao<Cat, Integer> getCatsDAO() {
        if (catDAO == null) {
            try {
                catDAO = getDao(Cat.class);
            } catch (java.sql.SQLException e) {
                e.printStackTrace();
            }
        }
        return catDAO;
    }

    public Dao<Kitten, Integer> getKittenDAO() {
        if (kittenDAO == null) {
            try {
                kittenDAO = getDao(Kitten.class);
            } catch (java.sql.SQLException e) {
                e.printStackTrace();
            }
        }
        return kittenDAO;
    }
}
    We need one more class that will encapsulate all the interactions with the DAO in the same package, let's create a basic code for it, and then we will add methods gradually as we need them in code. Through this class, define the way to display/update/delete table records/POJOs through DAO. In Activities/Adapter code, we will mainly work with this class:
package info.devexchanges.ormlite.database;

import android.content.Context;

import com.j256.ormlite.stmt.DeleteBuilder;

import java.sql.SQLException;
import java.util.ArrayList;

import info.devexchanges.ormlite.model.Cat;
import info.devexchanges.ormlite.model.Kitten;

public class DatabaseManager {

    private static DatabaseManager instance;
    private DatabaseHelper helper;

    public static void init(Context ctx) {
        if (null == instance) {
            instance = new DatabaseManager(ctx);
        }
    }

    static public DatabaseManager getInstance() {
        return instance;
    }

    private DatabaseManager(Context ctx) {
        helper = new DatabaseHelper(ctx);
    }

    public DatabaseHelper getHelper() {
        return helper;
    }

    /**
     * Get all customer in db
     *
     * @return
     */
    public ArrayList<Cat> getAllCats() {
        ArrayList<Cat> cats = null;
        try {
            cats = (ArrayList<Cat>) getHelper().getCatsDAO().queryForAll();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return cats;
    }

    public void addCat(Cat cat) {
        try {
            getHelper().getCatsDAO().create(cat);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void refreshCat(Cat cat) {
        try {
            getHelper().getCatsDAO().refresh(cat);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void updateCat(Cat wishList) {
        try {
            getHelper().getCatsDAO().update(wishList);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void deleteCat (int catId) {
        try {
            DeleteBuilder<Cat, Integer> deleteBuilder = getHelper().getCatsDAO().deleteBuilder();
            deleteBuilder.where().eq("id", catId);
            deleteBuilder.delete();

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public Kitten newKitten() {
        Kitten kitten = new Kitten();
        try {
            getHelper().getKittenDAO().create(kitten);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return kitten;
    }

    public Kitten newKittenAppend(Kitten kitten) {
        try {
            getHelper().getKittenDAO().create(kitten);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return kitten;
    }

    public void updateKitten(Kitten item) {
        try {
            getHelper().getKittenDAO().update(item);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public ArrayList<Kitten> getAllKittens() {
        ArrayList<Kitten> kittenArrayList = null;
        try {
            kittenArrayList = (ArrayList<Kitten>) getHelper().getKittenDAO().queryForAll();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return kittenArrayList;
    }

    public void deleteKitten (int kittenId) {
        try {
            DeleteBuilder<Kitten, Integer> deleteBuilder = getHelper().getKittenDAO().deleteBuilder();
            deleteBuilder.where().eq("id", kittenId);
            deleteBuilder.delete();

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Display data to Views

    At main activity, we will get data from database to views (ExpandableListView). Firstly, at onCreate(), initialize database by this line:
DatabaseManager.init(this);
    Get all tables records by DAO and save to ArrayList objects:
        //get all data to Lists
        ArrayList<Cat> catArrayList = DatabaseManager.getInstance().getAllCats();
    No more specials, we have full code for main activity:
package info.devexchanges.ormlite.activity;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import info.devexchanges.ormlite.R;
import info.devexchanges.ormlite.adapter.ExpandableListAdapter;
import info.devexchanges.ormlite.database.DatabaseManager;
import info.devexchanges.ormlite.model.Cat;
import info.devexchanges.ormlite.model.Kitten;

public class MainActivity extends AppCompatActivity {

    private ProgressBar progressBar;
    private ExpandableListView listView;
    private TextView notice;
    private List<Cat> cats;
    private ExpandableListAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        DatabaseManager.init(this);

        notice = (TextView)findViewById(R.id.notice);
        listView = (ExpandableListView)findViewById(R.id.list_item);
        progressBar = (ProgressBar)findViewById(R.id.progress);

        cats = new ArrayList<>();
        //set data to views
        adapter = new ExpandableListAdapter(this, cats);
        listView.setAdapter(adapter);
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d("Main", "resume");
        getDataFromDB();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.add) {
            Intent i = new Intent(this, AddingActivity.class);
            startActivity(i);

            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public void getDataFromDB() {
        if (cats != null) cats.clear();

        //get all data to Lists
        ArrayList<Cat> catArrayList = DatabaseManager.getInstance().getAllCats();
        for (int i = 0; i < catArrayList.size(); i++) {
            cats.add(catArrayList.get(i));
        }

        if (cats.size() == 0) {
            //no data in database
            listView.setVisibility(View.GONE);
            notice.setText("Database is Empty");
            notice.setVisibility(View.VISIBLE);
        } else {
            adapter.notifyDataSetChanged();
        }
    }
}
    Layout for this activity:

Adding new items

    Like display code above, saving a new Cat object to database through call:
//save new object to db
DatabaseManager.getInstance().addCat(cat);
    And add a Kitten is more complicate:
                        //save to database
                        DatabaseManager.getInstance().newKittenAppend(kitten);
                        DatabaseManager.getInstance().updateKitten(kitten);
    This "adding items" process has been written in an activity, and this is full code for it:
package info.devexchanges.ormlite.activity;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import info.devexchanges.ormlite.R;
import info.devexchanges.ormlite.database.DatabaseManager;
import info.devexchanges.ormlite.model.Cat;
import info.devexchanges.ormlite.model.Kitten;

public class AddingActivity extends AppCompatActivity {

    private View btnAddCat;
    private View btnAddKitten;
    private View btnOK;
    private Spinner spinner;
    private ViewGroup layoutAddCat;
    private ViewGroup layoutAddKitten;
    private ViewGroup layoutButtons;
    private EditText editCat;
    private EditText editKitten;
    private View btnCancel;
    private List<Cat> cats;
    private boolean havingCat = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_adding);

        btnAddCat = findViewById(R.id.btn_add_cat);
        btnOK = findViewById(R.id.btn_ok);
        layoutAddKitten = (ViewGroup) findViewById(R.id.ll_kit);
        layoutAddCat = (ViewGroup) findViewById(R.id.ll_cat);
        layoutButtons = (ViewGroup) findViewById(R.id.ll_buttons);
        btnCancel = findViewById(R.id.btn_cancel);
        spinner = (Spinner) findViewById(R.id.spinner);
        btnAddKitten = findViewById(R.id.btn_add_kitten);
        editCat = (EditText) findViewById(R.id.txt_name);
        editKitten = (EditText) findViewById(R.id.txt_kitten_name);

        btnAddKitten.setOnClickListener(onAddKittenListener());
        btnAddCat.setOnClickListener(onAddCatListner());
        btnCancel.setOnClickListener(onCancelListener());
        btnOK.setOnClickListener(onConfirmListener());
    }

    private View.OnClickListener onConfirmListener() {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (layoutAddCat.getVisibility() == View.VISIBLE) {
                    if (editCat.getText().toString().trim().equals("")) {
                        Toast.makeText(getBaseContext(), "Please input cat name", Toast.LENGTH_SHORT).show();
                    } else {
                        Cat cat = new Cat();
                        cat.setName(editCat.getText().toString().trim());

                        //save new object to db
                        DatabaseManager.getInstance().addCat(cat);
                    }
                } else if (layoutAddKitten.getVisibility() == View.VISIBLE) {
                    if (editKitten.getText().toString().trim().equals("")) {
                        Toast.makeText(getBaseContext(), "Please input kitten name", Toast.LENGTH_SHORT).show();
                    } else {
                        Kitten kitten = new Kitten();
                        Cat cat = (Cat) spinner.getSelectedItem();
                        kitten.setName(editKitten.getText().toString().trim());
                        kitten.setCat(cat);

                        //save to database
                        DatabaseManager.getInstance().newKittenAppend(kitten);
                        DatabaseManager.getInstance().updateKitten(kitten);
                    }
                }
                goneLayouts();
            }
        };
    }

    private View.OnClickListener onCancelListener() {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                goneLayouts();
            }
        };
    }

    private View.OnClickListener onAddCatListner() {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                goneLayouts();
                layoutAddCat.setVisibility(View.VISIBLE);
                layoutButtons.setVisibility(View.VISIBLE);
            }
        };
    }

    private View.OnClickListener onAddKittenListener() {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!havingCat) {
                    Toast.makeText(getBaseContext(), "None Cat in DB, please add cat first", Toast.LENGTH_SHORT).show();
                } else {
                    goneLayouts();

                    cats = DatabaseManager.getInstance().getAllCats();
                    if (cats.size() == 0) {
                        havingCat = false;
                    } else {
                        //set spinner adapter
                        ArrayAdapter<Cat> adapter = new ArrayAdapter<>(AddingActivity.this,
                                android.R.layout.simple_dropdown_item_1line, cats);
                        spinner.setAdapter(adapter);
                    }
                    layoutAddKitten.setVisibility(View.VISIBLE);
                    layoutButtons.setVisibility(View.VISIBLE);
                }
            }
        };
    }

    private void goneLayouts() {
        layoutAddCat.setVisibility(View.GONE);
        layoutAddKitten.setVisibility(View.GONE);
        layoutButtons.setVisibility(View.GONE);
        editCat.setText("");
        editKitten.setText("");
    }
}
    And it's layout:
    Output for this screen:

Editing/Updating an item

    From now, we open the ExpandableListview adapter class - extends from BaseExpendableListAdapter - (ExpandableListAdapter.java) to perform code for editing action. We can modify both Cat and Kitten name by clicking Edit Button in each row/header:
private View.OnClickListener onEditCatListener(final Cat cat, final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(activity);
                alertDialog.setTitle("EDIT Cat");
                alertDialog.setMessage("Please type a new cat name");

                final EditText input = new EditText(activity);
                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.MATCH_PARENT);
                input.setLayoutParams(lp);
                input.setText(cat.getName());

                alertDialog.setView(input);
                alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {

                        //update database with new cat name
                        cat.setName(input.getText().toString().trim());
                        DatabaseManager.getInstance().updateCat(cat);

                        //update views
                        cats.get(position).setName(input.getText().toString().trim());
                        notifyDataSetChanged();
                    }
                });

                alertDialog.setNegativeButton("Cancel", null);
                alertDialog.show();
            }
        };
    }

    private View.OnClickListener onEditKittenListener(final Kitten kitten, final int groupPos,
                                                      final int childPos) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(activity);
                alertDialog.setTitle("EDIT Kitten");
                alertDialog.setMessage("Please type a new kitten name");

                final EditText input = new EditText(activity);
                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.MATCH_PARENT);
                input.setLayoutParams(lp);
                input.setText(kitten.getName());

                alertDialog.setView(input);
                alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {

                        //update database
                        kitten.setName(input.getText().toString().trim());
                        DatabaseManager.getInstance().updateKitten(kitten);

                        //update views
                        cats.get(groupPos).getKittens().get(childPos).setName(input.getText().toString());
                        notifyDataSetChanged();
                    }
                });

                alertDialog.setNegativeButton("Cancel", null);
                alertDialog.show();
            }
        };
    }

    Output of this action:

Deleting an item

    Similar with editing action, we still coding in adapter class. This action was done by clicking Delete Button:
private View.OnClickListener onDeleteKittenListener(final int groupPosition, final int childPosition) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(activity);
                alertDialog.setTitle("Delete?");
                alertDialog.setMessage("Are you sure to delete?");

                alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        //delete in database
                        DatabaseManager.getInstance().deleteKitten(getChild(groupPosition, childPosition).getId());

                        //update views
                        activity.getDataFromDB();
                    }
                });

                alertDialog.setNegativeButton("Cancel", null);
                alertDialog.show();
            }
        };
    }

    private View.OnClickListener onDeleteCatListener(final int groupPosition) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(activity);
                alertDialog.setTitle("Delete?");
                alertDialog.setMessage("Are you sure to delete?");

                alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        //delete in database
                        DatabaseManager.getInstance().deleteCat(getGroup(groupPosition).getId());

                        //update views
                        cats.remove(groupPosition);
                        notifyDataSetChanged();
                    }
                });

                alertDialog.setNegativeButton("Cancel", null);
                alertDialog.show();
            }
        };
    }
    Output:

Final code

    The most important class in Expandable adapter. Overriding some requirement methods, we finally have full code:
package info.devexchanges.ormlite.adapter;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.List;

import info.devexchanges.ormlite.R;
import info.devexchanges.ormlite.activity.MainActivity;
import info.devexchanges.ormlite.database.DatabaseManager;
import info.devexchanges.ormlite.model.Cat;
import info.devexchanges.ormlite.model.Kitten;

public class ExpandableListAdapter extends BaseExpandableListAdapter {

    private MainActivity activity;
    private List<Cat> cats;

    public ExpandableListAdapter(MainActivity context, List<Cat> rows) {
        this.activity = context;
        this.cats = rows;
    }

    @Override
    public Kitten getChild(int groupPosition, int childPosititon) {
        return this.cats.get(groupPosition).getKittens().get(childPosititon);
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return getGroup(groupPosition).getKittens().size();
    }

    @Override
    public Cat getGroup(int groupPosition) {
        return this.cats.get(groupPosition);
    }

    @Override
    public int getGroupCount() {
        return cats.size();
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public View getChildView(int groupPosition, final int childPosition,
                             boolean isLastChild, View convertView, ViewGroup parent) {
        ChildViewHolder holder;
        LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.layout_child_list, parent, false);
            holder = new ChildViewHolder(convertView);
            convertView.setTag(holder);
        } else {
            holder = (ChildViewHolder) convertView.getTag();
        }

        holder.textView.setText(getChild(groupPosition, childPosition).getName());
        holder.btnEdit.setOnClickListener(onEditKittenListener(getChild(groupPosition, childPosition),
                groupPosition, childPosition));
        holder.btnDelete.setOnClickListener(onDeleteKittenListener(groupPosition, childPosition));

        return convertView;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        HeaderViewHolder holder;
        LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.layout_header_list, parent, false);
            holder = new HeaderViewHolder(convertView);
            convertView.setTag(holder);
        } else {
            holder = (HeaderViewHolder) convertView.getTag();
        }

        holder.textView.setText(getGroup(groupPosition).getName());
        holder.btnEdit.setOnClickListener(onEditCatListener(getGroup(groupPosition), groupPosition));
        holder.btnDelete.setOnClickListener(onDeleteCatListener(groupPosition));

        return convertView;
    }

    private View.OnClickListener onDeleteKittenListener(final int groupPosition, final int childPosition) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(activity);
                alertDialog.setTitle("Delete?");
                alertDialog.setMessage("Are you sure to delete?");

                alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        //delete in database
                        DatabaseManager.getInstance().deleteKitten(getChild(groupPosition, childPosition).getId());

                        //update views
                        activity.getDataFromDB();
                    }
                });

                alertDialog.setNegativeButton("Cancel", null);
                alertDialog.show();
            }
        };
    }

    private View.OnClickListener onDeleteCatListener(final int groupPosition) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(activity);
                alertDialog.setTitle("Delete?");
                alertDialog.setMessage("Are you sure to delete?");

                alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        //delete in database
                        DatabaseManager.getInstance().deleteCat(getGroup(groupPosition).getId());

                        //update views
                        cats.remove(groupPosition);
                        notifyDataSetChanged();
                    }
                });

                alertDialog.setNegativeButton("Cancel", null);
                alertDialog.show();
            }
        };
    }

    private View.OnClickListener onEditCatListener(final Cat cat, final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(activity);
                alertDialog.setTitle("EDIT Cat");
                alertDialog.setMessage("Please type a new cat name");

                final EditText input = new EditText(activity);
                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.MATCH_PARENT);
                input.setLayoutParams(lp);
                input.setText(cat.getName());

                alertDialog.setView(input);
                alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {

                        //update database with new cat name
                        cat.setName(input.getText().toString().trim());
                        DatabaseManager.getInstance().updateCat(cat);

                        //update views
                        cats.get(position).setName(input.getText().toString().trim());
                        notifyDataSetChanged();
                    }
                });

                alertDialog.setNegativeButton("Cancel", null);
                alertDialog.show();
            }
        };
    }

    private View.OnClickListener onEditKittenListener(final Kitten kitten, final int groupPos,
                                                      final int childPos) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(activity);
                alertDialog.setTitle("EDIT Kitten");
                alertDialog.setMessage("Please type a new kitten name");

                final EditText input = new EditText(activity);
                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.MATCH_PARENT);
                input.setLayoutParams(lp);
                input.setText(kitten.getName());

                alertDialog.setView(input);
                alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {

                        //update database
                        kitten.setName(input.getText().toString().trim());
                        DatabaseManager.getInstance().updateKitten(kitten);

                        //update views
                        cats.get(groupPos).getKittens().get(childPos).setName(input.getText().toString());
                        notifyDataSetChanged();
                    }
                });

                alertDialog.setNegativeButton("Cancel", null);
                alertDialog.show();
            }
        };
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }

    private static class ChildViewHolder {
        private TextView textView;
        private View btnEdit;
        private View btnDelete;

        public ChildViewHolder(View v) {
            textView = (TextView) v.findViewById(R.id.kitten_name);
            btnEdit = v.findViewById(R.id.edit);
            btnDelete = v.findViewById(R.id.delete);
        }
    }

    private static class HeaderViewHolder {
        private TextView textView;
        private View btnEdit;
        private View btnDelete;

        public HeaderViewHolder(View v) {
            btnDelete = v.findViewById(R.id.delete);
            textView = (TextView) v.findViewById(R.id.cat_name);
            btnEdit = v.findViewById(R.id.edit);
        }
    }
}
    Now, adding some necessary files to comple our project:
- ExpandableListView group layout, showing Cat name:
- ExpandableListView child layout, displaying Kitten name:
    Main screen after app launching:
- Strings resource:

Conclusions and References

    Through this post, I presented the solution to create and manage the SQLite through ORMLite. With this tools, I hope you can find out a simple way to using database, easy in code and maintainance, the "core processes" was deploy in libary code, shorten the time and reduce complexity for our work. By now, you can read official ORMLite docs page or see it's source code on Github to deep understanding about this powerful libary/tool, . Finally, thanks for reading and please subscribe me for newest tutorials!

https://github.com/DevExchanges/AndroidORMLiteExample

Share


Previous post
« Prev Post
Next post
Next Post »