Membuat Aplikasi Simple Note di Android – Pada Aplikasi ini kita akan menggunakan CRUD- adalah singkatan dari Create, Read, update, dan delete yang merupakan istilah dalam operasi query database. Bila kalian menggunakan android, maka class query database sudah ada di built in yaitu menggunakan Sqlite Database dan lebih bagus nya lagi sudah ada mekanisme dasarnya. Oleh hal tersebut akan sangat mudah sekali bila kita melakukan inheritance atas class tersebut. Gambaran awal mengenai Aplikasi CRUD di Android yang kita buat diberikan nama dengan Simple Note.
Desain UI Simple Note
Contents
Sesuai dengan namanya yaitu Simple Note yang fokus terhadap fungsionalitas, maka desainya cukup sederhana yaitu sebagai berikut yaitu ada 2 Activity yaitu
- TampilData
- EditTambahNote
dengan tampilan UI yang sederhana
Struktur Kode Java
Sebelum membuat kode yang panjang, saya akan kasih gambaran umum kode *.java nya terlebih dahulu, Aplikasi CRUD di Android terdiri dari 5 class yaitu
Penjelasan Mengenai Class Setting.java
Digunakan untuk memberikan informasi umum seperti versi database yang digunakan, serta pengaturan mode yaitu EDIT atau TAMBAH DATA BARU karena ketika tampil activity berikut
bisa digunakan untuk
- edit note yang sudah ada atau untuk
- menambah data baru sehingga hemat penggunaan activitynya
Caranya yaitu dengan membuat memasukan Bundle kedalam Intent misalkan untuk kasih FLAG bahwa Activity tersebut digunakan untuk TAMBAH DATA BARU maka cukup kasih Bundle
Intent intent = new Intent(TampilData.this,EditTambahNote.class); Bundle bundle = new Bundle(); bundle.putInt(Setting.STATUS,Setting.TAMBAH_DATA_BARU); intent.putExtras(bundle); startActivity(intent); finish();
Bila Activity tersebut untuk EDIT maka gunakan kode berikut (beserta kasih ID recordnya juga)
Intent intent = new Intent(TampilData.this,EditTambahNote.class); Bundle bundle = new Bundle(); bundle.putInt(Setting.STATUS,Setting.EDIT_DATA_LAMA); bundle.putInt(Note.clm_id,Integer.valueOf(getId.getText().toString())); //ID record intent.putExtras(bundle); startActivity(intent);
Berikut kode yang Setting.java
Terdiri dari static final agar tidak perlu buat instance dan tidak diubah nilainya!
public class Setting { public static final String STATUS = "status"; //untuk KEY di BUNDLE public static final int TAMBAH_DATA_BARU = 1; //untuk VALUE di BUNDLE public static final int EDIT_DATA_LAMA = 2; //untuk VALUE di BUNDLE public static final int VERSI_DB = 2; //versi database yang digunakan }
Desain tabel
Desain tabel terdiri dari 4 kolom yaitu
Perhatikan kolom dengan nama _id itu adalah wajib! tidak boleh menggunakan id atau ID karena itu nama default pada saat kita memanggil class Cursor Adapter yaitu class bawaan SDK android yang digunakan untuk mempermudah kita menampilkan records kedalam List View.
Urusan Database kita serahkan pada 2 class yaitu Note.java dan NoteCursorAdapter.java keduanya digunakan untuk
- Note.java adalah inheritance SQLiteOpenHelper yang digunakan untuk mempermudah urusan CRUD mulai create table, insert, update, dan delete
- NoteCursorAdapter.java digunakan untuk menampilkan hasil query SELECT * FROM table yang ditampung hasilnya menggunakan component List View istilah lainnya mempopulasikan data.
Berikut kode yang Node.java
Kode Node.java agak panjang yang didalammya sudah ada method2 yang sudah cukup memadai kita membuat aplikasi Simple Note
public class Note extends SQLiteOpenHelper { static final String database_name = "dbnote2"; static final String table_name = "tbnote"; static final String clm_id = "_id"; //wajib _id static final String clm_tanggal = "tanggal"; public final static String clm_title = "title"; public final static String clm_content = "content"; SQLiteDatabase db; public Note(Context context) { super(context, database_name, null, Setting.VERSI_DB); db = getWritableDatabase(); } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { //https://stackoverflow.com/questions/47848445/sqlite-database-error-during-execsql db = sqLiteDatabase; String query = "CREATE TABLE " + table_name + "(" + clm_id + " INTEGER PRIMARY KEY AUTOINCREMENT," + clm_tanggal + " TEXT, " + clm_title + " TEXT, " + clm_content + " TEXT)"; System.out.println(query); db.execSQL(query); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { db.execSQL("DROP TABLE IF EXISTS " + table_name); } //Get All SQLite Data public Cursor allData(){ Cursor cur = db.rawQuery("SELECT * FROM " + table_name , null); return cur; } //Get 1 Data By ID public Cursor oneData(Long id){ Cursor cur = db.rawQuery("SELECT * FROM " + table_name + " WHERE " + clm_id + "=" + id, null); return cur; } //Insert Data to Database public void insertData(ContentValues values){ db.insert(table_name, null, values); } //Update Data public void updateData(ContentValues values, long id){ db.update(table_name, values, clm_id + "=" + id, null); } //Delete Data public void deleteData(long id){ db.delete(table_name, clm_id + "=" + id, null); } }
Sebelum lanjut ke NoteCursorAdapter.java yang bertugas untuk menampilkan record/mempopulasikan data, kita buat terlebih dahulu layout xml untuk menampung record tersebut, agar mudah kita berikan nama layout/record_note.xml yang isinya sebagai berikut
Kode layout/record_note.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/listid" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="id" android:textAppearance="?android:attr/textAppearanceLarge" /> <TextView android:id="@+id/listtanggal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:text="tanggal"/> <TextView android:id="@+id/listtitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="title" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/listcontent" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:text="content"/> </LinearLayout>
Tampilan render diatas seperti berikut dibuat marginLeft berbeda-beda untuk membedakan antara title dan content
Setelah kita buat layout/record_note.xml diatas, kita lanjutkan NoteCursorAdapter.java
Kode NoteCursorAdapter.java
Bertugas menampilkan record
public class NoteCursorAdapter extends CursorAdapter { public NoteCursorAdapter(Context context, Cursor cursor) { super(context, cursor, Setting.VERSI_DB); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View inflater = LayoutInflater.from(context).inflate(R.layout.record_note,parent, false); return inflater; } @Override public void bindView(View view, Context context, Cursor cursor) { TextView id = (TextView) view.findViewById(R.id.listid); TextView tanggal = (TextView) view.findViewById(R.id.listtanggal); TextView title = (TextView) view.findViewById(R.id.listtitle); TextView content = (TextView) view.findViewById(R.id.listcontent); //get cursor String string_id = cursor.getString(cursor.getColumnIndexOrThrow(Note.clm_id)); String string_tanggal = cursor.getString(cursor.getColumnIndexOrThrow(Note.clm_tanggal)); String string_title = cursor.getString(cursor.getColumnIndexOrThrow(Note.clm_title)); String string_content = cursor.getString(cursor.getColumnIndexOrThrow(Note.clm_content)); id.setText(string_id); tanggal.setText(string_tanggal); title.setText(string_title); content.setText(string_content); } }
Perhatikan method newView yang mengembalikan return berupa View
Setelah kita membuat 3 class diatas dan 1 layout untuk menampung record, sekarang kita buat 2 class yang bertugas untuk menampilkan dan edit/tambah record dalam bentuk activity
Membuat Tampil Data
TampilData.java mempunyai kode yang cukup panjang, didalamnya method loadagain() yang merupakan load record dengan cara memanggil NoteCursorAdapter sebagai argument input pada List View. Didalamnya Activity Tampil Data juga diberikan action listener ketika user klik List View tersebut akan diberikan pilihan untuk Edit / Hapus / Batal
kode layout/activity_tampil_data.xml
Berikut tampilan dari layout/activity_tampil_data.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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="wrap_content" tools:context=".TampilData" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="5dp"> <Button android:id="@+id/back_tambah" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="tulis note" android:layout_margin="5dp"/> <Button android:id="@+id/keluar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="keluar" android:layout_margin="5dp"/> </LinearLayout> <ListView android:id="@+id/list_data" android:layout_width="match_parent" android:layout_height="match_parent" android:drawSelectorOnTop="true" android:layout_margin="7dp"/> </LinearLayout>
Component List View akan menampung record
Kode Activity TampilData.java
Berikut kode nya cukup ringkas koq
public class TampilData extends AppCompatActivity implements AdapterView.OnItemClickListener { private Note dbhelper; private ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_tampil_data); dbhelper = new Note(this); listView = (ListView)findViewById(R.id.list_data); listView.setOnItemClickListener(this); //biar pas di sentuh ada action listener loadagain(); Button tambah_note_baru = (Button) findViewById(R.id.back_tambah); tambah_note_baru.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()){ case R.id.back_tambah: Intent intent = new Intent(TampilData.this,EditTambahNote.class); Bundle bundle = new Bundle(); bundle.putInt(Setting.STATUS,Setting.TAMBAH_DATA_BARU); //kasih flag intent.putExtras(bundle); //bahwa Inten yang dibuat untuk startActivity(intent); //TAMBAH DATA BARU finish(); break; } } }); Button keluar = (Button) findViewById(R.id.keluar); keluar.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()){ case R.id.keluar: finishAffinity(); break; } } }); } private void loadagain(){ Cursor cursor = dbhelper.allData(); NoteCursorAdapter customCursorAdapter = new NoteCursorAdapter(this, cursor); listView.setAdapter(customCursorAdapter); } @Override public void onItemClick(AdapterView<?> parent, View view, int i, long x) { TextView getId = (TextView)view.findViewById(R.id.listid); final long id = Long.parseLong(getId.getText().toString()); final AlertDialog.Builder builder = new AlertDialog.Builder(TampilData.this); builder.setTitle("Menu : "); String [] opsi = new String[]{"Edit","Hapus","Batal"}; builder.setItems(opsi,new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which) { switch(which){ case 0: Intent intent = new Intent(TampilData.this,EditTambahNote.class); Bundle bundle = new Bundle(); bundle.putInt(Setting.STATUS,Setting.EDIT_DATA_LAMA); //kasih flag bundle.putInt(Note.clm_id,Integer.valueOf(getId.getText().toString())); //ID record intent.putExtras(bundle); startActivity(intent); break; case 1: dbhelper.deleteData(id); loadagain(); break; case 2: //do nothing break; } } }); AlertDialog dialog = builder.create(); dialog.show(); } }
Berikut tampilan aplikasi ketika ada record yang sudah tersimpan
Membuat Edit Tambah Note
Sekarang kita buat activity EDIT TAMBAH, seperti yang sudah dijelaskan sebelumnya bahwa activity ini bisa digunakan untuk EDIT dan TAMBAH. Trik yang kita lakukan yaitu menyembunyikan component TextView untuk menampung _id record ketika dalam mode EDIT android:visibility="gone"
, ya mirip-mirip HIDDEN pada TAG HTML
Oiya untuk Tanggal akan dibuat otomatis diambil dari ponsel, agar ada gambaran, kita buat saja
Kode layout/activity_edit_tambah_note.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical" tools:context=".EditTambahNote"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/tambah_note" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="3dp" android:text="tambah"/> <Button android:id="@+id/simpan_note" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_margin="3dp" android:text="simpan"/> <Button android:id="@+id/lihat_note" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_margin="3dp" android:text="lihat"/> </LinearLayout> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/id_note" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone"/> <EditText android:id="@+id/title" android:layout_width="match_parent" android:layout_height="match_parent" android:hint="title"/> <EditText android:id="@+id/content" android:layout_width="match_parent" android:layout_height="142dp" android:hint="content" /> </LinearLayout> </ScrollView> </LinearLayout>
Berikut hasil render diatas
Yuk buat Activity nya
Kode Activity EditTambahNote.java
public class EditTambahNote extends AppCompatActivity { int STATUS; int ID_NOTE; Note dbhelper; EditText id_note,title_note,content_note; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_edit_tambah_note); dbhelper = new Note(this); Button tambah_note = (Button) findViewById(R.id.tambah_note); Button simpan_note = (Button)findViewById(R.id.simpan_note); Button lihat_note = (Button) findViewById(R.id.lihat_note); id_note = (EditText) findViewById(R.id.id_note); title_note = (EditText) findViewById(R.id.title); content_note = (EditText) findViewById(R.id.content); Bundle bundel = getIntent().getExtras(); STATUS = bundel.getInt(Setting.STATUS); if(STATUS==Setting.EDIT_DATA_LAMA){ //cek flag nya dulu ID_NOTE = (int) bundel.getInt(Note.clm_id); Cursor cursor = dbhelper.oneData((long)ID_NOTE); cursor.moveToFirst();//untuk memastikan pertama! System.out.println("ID NOTE: "+ID_NOTE); String string_id = cursor.getString(cursor.getColumnIndexOrThrow(Note.clm_id)); String string_tanggal = cursor.getString(cursor.getColumnIndexOrThrow(Note.clm_tanggal)); String string_title = cursor.getString(cursor.getColumnIndexOrThrow(Note.clm_title)); String string_content = cursor.getString(cursor.getColumnIndexOrThrow(Note.clm_content)); id_note.setText(String.valueOf(ID_NOTE)); title_note.setText(string_title); content_note.setText(string_content); cursor.close(); }else{ // tak lakukan apapun } simpan_note.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { switch (v.getId()){ case R.id.simpan_note: if(STATUS==Setting.TAMBAH_DATA_BARU){ if(title_note.getText().toString().equals("")){ Toast.makeText(EditTambahNote.this, "Tak Jadi Simpan", Toast.LENGTH_SHORT).show(); return; } Date currentTime = Calendar.getInstance().getTime(); ContentValues values = new ContentValues(); values.put(dbhelper.clm_title,title_note.getText().toString().trim()); values.put(dbhelper.clm_content,content_note.getText().toString().trim()); values.put(dbhelper.clm_tanggal,currentTime.toString()); dbhelper.insertData(values); Toast.makeText(EditTambahNote.this, "1 Note telah tersimpan", Toast.LENGTH_SHORT).show(); Intent home = new Intent(EditTambahNote.this,TampilData.class); startActivity(home); } if(STATUS==Setting.EDIT_DATA_LAMA){ Date currentTime = Calendar.getInstance().getTime(); ContentValues values = new ContentValues(); values.put(dbhelper.clm_id,String.valueOf(ID_NOTE)); values.put(dbhelper.clm_title,title_note.getText().toString().trim()); values.put(dbhelper.clm_content,content_note.getText().toString().trim()); values.put(dbhelper.clm_tanggal,currentTime.toString()); dbhelper.updateData(values,ID_NOTE); Toast.makeText(EditTambahNote.this, "Simpan data lama!!", Toast.LENGTH_SHORT).show(); } break; } } }); lihat_note.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { switch (v.getId()){ case R.id.lihat_note: Intent home = new Intent(EditTambahNote.this,TampilData.class); startActivity(home); } } }); tambah_note.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()){ case R.id.tambah_note: //hapus yang ada id_note.setText(""); title_note.setText(""); content_note.setText(""); STATUS = Setting.TAMBAH_DATA_BARU; break; } } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Membaca file menu dan menambahkan isinya ke action bar jika ada. getMenuInflater().inflate(R.menu.main_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle presses on the action bar items switch (item.getItemId()) { case R.id.miCompose: //action return true; case R.id.miProfile: //action return true; default: return super.onOptionsItemSelected(item); } } }
Main Activity
Pada main Activity kita kasih kode berikut untuk memanggil pertama kali berupa tampil record
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //getSupportActionBar().hide(); Intent home = new Intent(MainActivity.this,TampilData.class); startActivity(home); } }
Kesimpulan
Bagaimana menurut kalian? tentu Aplikasi CRUD di Android diatas kurang fiturnya tapi pada dasarnya tutorial diatas sebagai basic saja agar paham dulu mengenai cara membuat Aplikasi CRUD di Android. Aplikasi diatas telah saya gunakan untuk mempermudah buat catatan di ponsel android dan sangat membantu sih. Aplikasi diatas sengaja menyimpan tanggal secara otomatis seharusnya sih ORDER BY tanggal ketika menampilkan record agar lebih urut update tanggal terbaru. Caranya adalah date time diubah kedalam integer (mengingat sqlite tidak punya format penyimpanan date) sehingga ketika formatnya integer akan mudah perintah sql menjadi ORDER BY tanggal.
Bila kalian ingin mengedit database secara langsung, bisa menggunakan database inspector
Download Source Code
Untuk source code saya letakan di https://github.com/mulkan/SimpleNote tapi sudah ada beberapa perubahan