greenDAO CRUD Demo Application
This is a sequel to Integrating greenDao into your android application
Had to write this post due to requests for a demo app using GreenDao ORM. So lets list the feature of our GreenDAO CRUD App. CRUD stands for Create, Read, Delete & Update.
- Add item to grocery list (Create)
- list all groceries items added (Read)
- Update grocery list (Update)
- Remove grocery Item (Delete)
So we will be creating a new Android project called OurGroceryApp. Please go through Seting up GreenDao ORM. Follow Step 2 through Step 6.
Then on Step 6 insead of creating entity User with fields user_id, last_name, first_name and email.
We will be creating an entity named Grocery with fields name,quantity and status. This is what our MyGenerator Class looks like now
package com.example;
import org.greenrobot.greendao.generator.DaoGenerator;
import org.greenrobot.greendao.generator.Entity;
import org.greenrobot.greendao.generator.Schema;
public class MyGenerator {
public static void main(String[] args) {
Schema schema = new Schema(1, "com.akinsete.ourgrocerylist.db"); // Your app package name and the (.db) is the folder where the DAO files will be generated into.
schema.enableKeepSectionsByDefault();
addTables(schema);
try {
new DaoGenerator().generateAll(schema,"./app/src/main/java");
} catch (Exception e) {
e.printStackTrace();
}
}
private static void addTables(final Schema schema) {
addGroceryEntity(schema);
}
// This is use to describe the columns of your table
private static Entity addGroceryEntity(final Schema schema) {
Entity grocery = schema.addEntity("Grocery");
grocery.addIdProperty().primaryKey().autoincrement();
grocery.addStringProperty("name").notNull();
grocery.addIntProperty("quantity").notNull();
grocery.addStringProperty("status");
return grocery;
}
}
Right on the MyGenerator Class and Run "MyGenerator.run()". After this we will now have our DAO files, entities generated in our main project.
So proceed to Step 8
Creata a class to extend Application. See Application file after adding greenDAO to enable easy access from all our activities.
package com.akinsete.ourgrocerylist;
import android.app.Application;
import com.akinsete.ourgrocerylist.db.DaoMaster;
import com.akinsete.ourgrocerylist.db.DaoSession;
import org.greenrobot.greendao.database.Database;
/**
* Created by Akinsete on 6/30/17.
*/
public class AppController extends Application {
public static final boolean ENCRYPTED = true;
private DaoSession daoSession;
@Override
public void onCreate() {
super.onCreate();
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this,"grocery-db"); //The users-db here is the name of our database.
Database db = helper.getWritableDb();
daoSession = new DaoMaster(db).newSession();
}
public DaoSession getDaoSession() {
return daoSession;
}
}
Now add a ListView to display our Grocery List and a FAB to navigate to add more item to our list. The listview will be used for displaying out grocery list, deleting an item and also to modify items on the grocery list.
So back to greenDAO, In our MainActivity do the following.
- Create a DAOSession variable and a Grocery list varaible from our Grocery model class;
DaoSession daoSession;
List<Grocery> groceries = new ArrayList<>();
- In the OnCreate method get the DAOSession from or AppController class
daoSession = ((AppController) getApplication()).getDaoSession();
- On this particular activity we will be performing 3 major operations.
a. fetch out grocery list
b. delete an item on the grocery list
c. get selected item to update then pass the item to the modify activity
So we will have
private void fetchGroceryList(){
groceries.clear();
//// Get the entity dao we need to work with.
GroceryDao groceryDao = daoSession.getGroceryDao();
//// Load all items
groceries.addAll(groceryDao.loadAll());
/// Notify our adapter of changes
groceryArrayAdapter.notifyDataSetChanged();
}
private void deleteGroceryItem(long id){
//// Get the entity dao we need to work with.
GroceryDao groceryDao = daoSession.getGroceryDao();
/// perform delete operation
groceryDao.deleteByKey(id);
fetchGroceryList();
}
private void proceedToUpdateItem(Grocery grocery){
// Pass grocery id to the next screen
Intent intent = new Intent(this,ModifyGroceryList.class);
intent.putExtra("create",false);
// make sure your Grocery Class implements seriallizable
intent.putExtra("grocery",grocery);
startActivity(intent);
}
So this is our main complete MainActivity.class.
package com.akinsete.ourgrocerylist;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.akinsete.ourgrocerylist.db.DaoSession;
import com.akinsete.ourgrocerylist.db.Grocery;
import com.akinsete.ourgrocerylist.db.GroceryDao;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
ListView listView;
List<Grocery> groceries = new ArrayList<>();
DaoSession daoSession;
ArrayAdapter<Grocery> groceryArrayAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.list_view);
daoSession = ((AppController) getApplication()).getDaoSession();
setupListView();
}
@Override
protected void onResume() {
super.onResume();
fetchGroceryList();
}
private void setupListView() {
groceryArrayAdapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,groceries);
listView.setAdapter(groceryArrayAdapter);
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
showOptions(position);
return false;
}
});
}
private void showOptions(int position) {
final Grocery selectedGroceryItem = groceries.get(position);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
String[] options = new String[2];
options[0] = "Edit " + selectedGroceryItem.getName();
options[1] = "Delete " + selectedGroceryItem.getName();
alertDialogBuilder.setItems(options, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(which == 0){
proceedToUpdateItem(selectedGroceryItem);
}else if(which == 1){
deleteGroceryItem(selectedGroceryItem.getId());
}
}
});
alertDialogBuilder.create().show();
}
private void fetchGroceryList(){
groceries.clear();
//// Get the entity dao we need to work with.
GroceryDao groceryDao = daoSession.getGroceryDao();
//// Load all items
groceries.addAll(groceryDao.loadAll());
/// Notify our adapter of changes
groceryArrayAdapter.notifyDataSetChanged();
}
private void deleteGroceryItem(long id){
//// Get the entity dao we need to work with.
GroceryDao groceryDao = daoSession.getGroceryDao();
/// perform delete operation
groceryDao.deleteByKey(id);
fetchGroceryList();
}
private void proceedToUpdateItem(Grocery grocery){
// Pass grocery id to the next screen
Intent intent = new Intent(this,ModifyGroceryList.class);
intent.putExtra("create",false);
intent.putExtra("grocery",grocery);
startActivity(intent);
}
public void addNewItem(View view) {
// Go to add item activity
Intent intent = new Intent(this,ModifyGroceryList.class);
intent.putExtra("create",true);
startActivity(intent);
}
}
Please note, there are lots of operations that can be performed on the groceryDao Object etc
groceryDao.deleteAll();
groceryDao.delete(grocery);
groceryDao.insert(grocery);
groceryDao.load(grocery_id);
groceryDao.insertOrReplaceInTx(groceryEntities);
and many more.
In our ModifyGroceryList.class Activity we will be performing 2 major greenDAO operations. Which is
1. Update a grocery item
2. Add new grocery item
private void updateItem(long id){
GroceryDao groceryDao = daoSession.getGroceryDao();
Grocery grocery = new Grocery();
grocery.setId(id);
grocery.setName(name.getText().toString());
grocery.setQuantity(Integer.parseInt(quantity.getText().toString()));
groceryDao.saveInTx(grocery);
Toast.makeText(this, "Item updated", Toast.LENGTH_SHORT).show();
finish();
}
private void insetItem(){
GroceryDao groceryDao = daoSession.getGroceryDao();
Grocery grocery = new Grocery();
grocery.setName(name.getText().toString());
grocery.setQuantity(Integer.parseInt(quantity.getText().toString()));
groceryDao.insert(grocery);
Toast.makeText(this, "Item inserted", Toast.LENGTH_SHORT).show();
finish();
}
And below is the complete ModifyGroceryList.class Activity
package com.akinsete.ourgrocerylist;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.akinsete.ourgrocerylist.db.DaoSession;
import com.akinsete.ourgrocerylist.db.Grocery;
import com.akinsete.ourgrocerylist.db.GroceryDao;
public class ModifyGroceryList extends AppCompatActivity {
Grocery grocery;
DaoSession daoSession;
EditText name,quantity;
Button btn_save;
boolean createNew = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_modify_grocery_list);
name = (EditText)findViewById(R.id.name);
quantity = (EditText)findViewById(R.id.quantity);
btn_save = (Button) findViewById(R.id.btn_save);
daoSession = ((AppController) getApplication()).getDaoSession();
handleIntent(getIntent());
setClickEventListener();
}
private void handleIntent(Intent intent) {
createNew = intent.getBooleanExtra("create",false);
//// This means we are editing a grocery item
if(!createNew){
grocery = (Grocery)intent.getSerializableExtra("grocery");
name.setText(grocery.getName());
quantity.setText(String.valueOf(grocery.getQuantity()));
}
}
private void setClickEventListener() {
btn_save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(createNew){
insetItem();
}else{
updateItem(grocery.getId());
}
}
});
}
private void updateItem(long id){
GroceryDao groceryDao = daoSession.getGroceryDao();
Grocery grocery = new Grocery();
grocery.setId(id);
grocery.setName(name.getText().toString());
grocery.setQuantity(Integer.parseInt(quantity.getText().toString()));
groceryDao.saveInTx(grocery);
Toast.makeText(this, "Item updated", Toast.LENGTH_SHORT).show();
finish();
}
private void insetItem(){
GroceryDao groceryDao = daoSession.getGroceryDao();
Grocery grocery = new Grocery();
grocery.setName(name.getText().toString());
grocery.setQuantity(Integer.parseInt(quantity.getText().toString()));
groceryDao.insert(grocery);
Toast.makeText(this, "Item inserted", Toast.LENGTH_SHORT).show();
finish();
}
}
And thats it for our grocery app. See Github Repo for complete project.
For those that requested for this sorry its coming little late. I have been busy.
Please do not hesitate to ask for more.
Thanks.
Why do I get this in my listView -> [Ljava.lang.String;@9d2d436
instead of Name and quantity?
Getting this error when trying to update… using your repository code. Any ideas?
2019-01-03 20:06:19.111 26312-26312/com.akinsete.ourgrocerylist E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.akinsete.ourgrocerylist, PID: 26312
java.lang.ClassCastException: com.akinsete.ourgrocerylist.db.Grocery cannot be cast to java.io.Serializable
at com.akinsete.ourgrocerylist.MainActivity.proceedToUpdateItem(MainActivity.java:120)
at com.akinsete.ourgrocerylist.MainActivity.access$100(MainActivity.java:21)
at com.akinsete.ourgrocerylist.MainActivity$2.onClick(MainActivity.java:82)
at com.android.internal.app.AlertController$AlertParams$3.onItemClick(AlertController.java:1119)
at android.widget.AdapterView.performItemClick(AdapterView.java:310)
at android.widget.AbsListView.performItemClick(AbsListView.java:1155)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3120)
at android.widget.AbsListView$3.run(AbsListView.java:4035)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
I’m getting the same error , do you have any idea to fix it?