My Diary | SQLite Database

Setelah kemarin membuat tutorial tentang CRUD untuk database online, tidak lengkap rasanya jika tidak membuat tutorial juga untuk database offline yaitu SQLite Database. Penggunaan SQLite untuk menyimpan data lokal sangat sering digunakan dalam aplikasi-aplikasi. Oleh karena itu, sangatlah perlu untuk mempelajari cara penggunaannya.

Tutorial kali ini, aplikasi yang akan saya buat adalah aplikasi My Diary. Dari namanya, aplikasi ini memang seperti buku diari pada umumnya. Saya membuat aplikasi tersebut, karena menurut saya penerapan CRUD untuk SQLite sudah mencakup semuanya. Seperti Create untuk menambahkan diary baru misalnya. Yang beda dari tutorial kali ini, aplikasi yang saya buat akan saya upload di playstore, jadi anda dapat dengan mudah untuk mencobanya dan juga sebagai tambahan portofolio saya, hehe.

Silahkan jika ingin mencobanya bisa didownload lewat playstore:

google_play

Tidak usah bertele-tele, kita mulai saja membuat aplikasi ini. Seperti biasa, saya akan menjelaskan alur dari pembuatan aplikasi ini, sebagai berikut:

  1. Menambahkan beberapa library pendukung
  2. Mendisain antar muka
  3. Coding Time

Library Pendukung

Seperti biasa, AppCompat tidak pernah ditinggalkan

com.android.support:appcompat-v7:23.0.1

Lalu saya menggunakan support design untuk mempercantik interface

com.android.support:design:23.0.1

Untuk list saya menggunakan recyclerview dengan itemnya menggunakan cardview, untuk memberikan efek shadow

com.android.support:recyclerview-v7:23.0.1
com.android.support:cardview-v7:23.0.1

Keseluruhannya seperti ini:

1

 

Antar Muka

Terdapat 4 activity, 1 activity bertemakan dialog, 1 activity untuk splash screen dan 2 lainnya sebagai activity utama dan activity diary. Dan juga terdapat 1 custom layout untuk item dari recyclerview.

Didalam projek ini juga digunakan beberapa gambar dan icon. Untuk icon bisa anda generate sendiri jika mempunyai plugin material design icon. Atau bisa juga copy paste dari sourcecode tutorial ini.

SplashScreen

device-2015-10-25-105120

activity_splash_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:fitsSystemWindows="true"
    tools:context="com.andevindo.andevindodiary.Activity.SplashScreenActivity"
    android:background="@color/colorPrimary">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageView"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:src="@drawable/logo"/>

    <ImageView
        android:layout_width="75dp"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:id="@+id/imageView2"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:src="@drawable/logo4"/>

    <ImageView
        android:layout_marginLeft="15dp"
        android:layout_width="125dp"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:id="@+id/imageView3"
        android:layout_alignBottom="@+id/imageView2"
        android:layout_alignLeft="@+id/imageView"
        android:src="@drawable/domainesia"/>

</RelativeLayout>

 

Menu Utama

device-2015-10-25-104958

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    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:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/ic_add_white_24dp"/>


</android.support.design.widget.CoordinatorLayout>

Menu utama menggunakan include untuk menambahkan layout lain dalam activity_main.xml ini.

content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_main"
    tools:context=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

 

Detail Diary

device-2015-10-25-105242

activity_detail.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.andevindo.andevindodiary.Activity.DetailActivity"
        android:orientation="vertical">

        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:textSize="20sp"
            android:fontFamily="@string/font_medium"
            android:alpha="0.87"/>

        <TextView
            android:id="@+id/content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:textSize="14sp"
            android:fontFamily="@string/font_regular"
            android:alpha="0.87"/>

        <TextView
            android:id="@+id/loc_date"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="12sp"
            android:fontFamily="@string/font_regular"
            android:alpha="0.54"/>

    </LinearLayout>
</ScrollView>

 

Diary Activity

Diary activity ini untuk membuat diary baru atau untuk merubah diary lama.

device-2015-10-25-105155

activity_diary.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    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:fitsSystemWindows="true"
    tools:context="com.andevindo.andevindodiary.Activity.DiaryActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_diary"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/ic_save_white_24dp"/>

</android.support.design.widget.CoordinatorLayout>
content_diary.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    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"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.andevindo.andevindodiary.Activity.DiaryActivity"
    tools:showIn="@layout/activity_diary"
    >

    <LinearLayout

        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        >

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp">

            <EditText
                android:id="@+id/title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Title"/>
        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:id="@+id/content"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Content"/>
        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp">

            <EditText
                android:id="@+id/location"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Location"/>
        </android.support.design.widget.TextInputLayout>

        <CheckBox
            android:id="@+id/update_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:text="Update time"/>

    </LinearLayout>

</ScrollView>

 

 

Custom Layout

Layout untuk item dari recyclerview

2

custom_list_diary.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"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <android.support.v7.widget.CardView
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:cardElevation="2dp"
        app:cardUseCompatPadding="true">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="16dp"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/title"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="8dp"
                    android:text="title"
                    android:fontFamily="@string/font_medium"
                    android:alpha="0.87"
                    android:textSize="20sp"/>

                <TextView
                    android:id="@+id/content"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginRight="16dp"
                    android:layout_marginBottom="8dp"
                    android:text="content"
                    android:fontFamily="@string/font_regular"
                    android:alpha="0.87"
                    android:textSize="14sp"/>

                <TextView
                    android:id="@+id/loc_date"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="loc and date"
                    android:fontFamily="@string/font_regular"
                    android:alpha="0.54"
                    android:textSize="12sp"/>
            </LinearLayout>

            <android.support.design.widget.FloatingActionButton
                android:id="@+id/fab"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom|right"
                android:layout_margin="8dp"
                android:src="@drawable/ic_mode_edit_white_24dp"
                app:elevation="0dp"
                app:fabSize="mini"/>
        </FrameLayout>


    </android.support.v7.widget.CardView>

</LinearLayout>

 

Beberapa values yang diperlukan:

colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#e91e63</color>
    <color name="colorPrimaryDark">#c2185b</color>
    <color name="colorAccent">#aa00ff</color>
</resources>
strings.xml
<resources>
    <string name="app_name">My Diary</string>
    <string name="action_settings">Settings</string>
    <string name="title_activity_diary">DiaryActivity</string>

    <string name="font_medium">sans-serif-medium</string>
    <string name="font_regular">sans-serif</string>

    <string name="title_activity_splash_screen">SplashScreenActivity</string>

</resources>
styles.xml
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>

    <style name="AppTheme.Dialog" parent="Theme.AppCompat.Light.Dialog">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="AppTheme.FullScreen" parent="AppTheme.NoActionBar">
        <item name="android:windowFullscreen">true</item>
    </style>

</resources>
styles.xml versi 21
<resources>
    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>

 

 

Coding Time 😀

Inilah screenshot dari projek saya

3

Terdapat package Utils yang berisikan sebuah class bernama TimeHelper, berfungsi untuk conversi waktu saat itu ke dalam bentuk String dengan format Jam:Menit Tanggal:Bulan:Tahun.

TimeHelper.java
package com.andevindo.andevindodiary.Utils;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by -H- on 10/24/2015.
 */
public class TimeHelper {

    public static String getTimeRightNow(){
        SimpleDateFormat desiredFormat = new SimpleDateFormat(
                "kk:mm dd-MM-yyyy");
        return desiredFormat.format(new Date());

    }

}

Kemudian terdapat package Model, berisikan sebuah class bernama Diary, ini sebagai model dari data diary.

Diary.java
package com.andevindo.andevindodiary.Model;

/**
 * Created by -H- on 10/24/2015.
 */
public class Diary {

    public static final String TABLE_NAME = "diary";
    public static final String ID = "id";
    public static final String TITLE = "title";
    public static final String CONTENT = "content";
    public static final String DATE = "date";
    public static final String LOCATION = "location";

    private int mId;
    private String mTitle;
    private String mContent;
    private String mDate;
    private String mLocation;

    public int getId() {
        return mId;
    }

    public void setId(int id) {
        mId = id;
    }


    public String getLocation() {
        return mLocation;
    }

    public void setLocation(String location) {
        mLocation = location;
    }

    public String getTitle() {
        return mTitle;
    }

    public void setTitle(String title) {
        mTitle = title;
    }

    public String getContent() {
        return mContent;
    }

    public void setContent(String content) {
        mContent = content;
    }

    public String getDate() {
        return mDate;
    }

    public void setDate(String date) {
        mDate = date;
    }
}

 

Kemudian ada package Database, tentunya didalamnya berhubungan dengan database. Terdapat class DatabaseHelper dan DiaryHelper. Database Helper, digunakan untuk membuat database, table diary. Dan juga untuk menempatkan beberapa method untuk CRUD.

DatabaseHelper.java
package com.andevindo.andevindodiary.Database;

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

import com.andevindo.andevindodiary.Model.Diary;

/**
 * Created by -H- on 10/24/2015.
 */
public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String sDiaryDB = "DIARY_DB";
    private static final int sVersion = 1;
    private static final String sCreateDiaryTable = "create table " + Diary.TABLE_NAME + "(" +
            Diary.ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
            Diary.TITLE + " TEXT, " +
            Diary.CONTENT + " TEXT, " +
            Diary.LOCATION + " TEXT, " +
            Diary.DATE + " TEXT)";

    public DatabaseHelper(Context context) {
        super(context, sDiaryDB, null, sVersion);
    }


    @Override
    public void onCreate(SQLiteDatabase db) {
        db.beginTransaction();
        db.execSQL(sCreateDiaryTable);
        db.setTransactionSuccessful();
        db.endTransaction();
    }

    public void update(Diary diary, SQLiteDatabase db) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(Diary.TITLE, diary.getTitle());
        contentValues.put(Diary.CONTENT, diary.getContent());
        contentValues.put(Diary.LOCATION, diary.getLocation());
        contentValues.put(Diary.DATE, diary.getDate());
        db.update(Diary.TABLE_NAME, contentValues, Diary.ID + "=" + diary.getId(), null);
    }

    public void insert(Diary diary, SQLiteDatabase db) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(Diary.TITLE, diary.getTitle());
        contentValues.put(Diary.CONTENT, diary.getContent());
        contentValues.put(Diary.LOCATION, diary.getLocation());
        contentValues.put(Diary.DATE, diary.getDate());
        db.insertOrThrow(Diary.TABLE_NAME, null, contentValues);

    }

    public void delete(int id, SQLiteDatabase db) {
        db.delete(Diary.TABLE_NAME, Diary.ID + "=" + id, null);
    }

    public void deleteAll(SQLiteDatabase db){
        db.delete(Diary.TABLE_NAME, null, null);
    }


    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

Diary Helper berisikan beberapa method untuk CRUD juga namun dengan beberapa tambahan, seperti beginTransaction yang berfungsi untuk memulai proses query database. Dan juga berisi converter, dari cursor ke diary.

DiaryHelper.java
package com.andevindo.andevindodiary.Database;

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

import com.andevindo.andevindodiary.Model.Diary;

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

/**
 * Created by -H- on 10/24/2015.
 */
public class DiaryHelper {

    private static SQLiteDatabase getWritableAndOpen(DatabaseHelper databaseHelper){
        SQLiteDatabase sqLiteDatabase = databaseHelper.getWritableDatabase();
        sqLiteDatabase.beginTransaction();
        return sqLiteDatabase;
    }

    private static SQLiteDatabase getReadableAndOpen(DatabaseHelper databaseHelper){
        SQLiteDatabase sqLiteDatabase = databaseHelper.getReadableDatabase();
        sqLiteDatabase.beginTransaction();
        return sqLiteDatabase;
    }

    private static void closeTransaction(SQLiteDatabase sqLiteDatabase){
        sqLiteDatabase.setTransactionSuccessful();
        sqLiteDatabase.endTransaction();
    }

    public static List<Diary> getDiaries(Context context){
        DatabaseHelper databaseHelper = new DatabaseHelper(context);
        SQLiteDatabase sqLiteDatabase = getReadableAndOpen(databaseHelper);
        Cursor cursor = sqLiteDatabase.query(Diary.TABLE_NAME, null, null, null, null, null, Diary.DATE + " DESC");
        closeTransaction(sqLiteDatabase);
        List<Diary> list = convertCursorToList(cursor);
        cursor.close();
        return list;
    }

    public static Diary getDiary(Context context, int id){
        DatabaseHelper databaseHelper = new DatabaseHelper(context);
        SQLiteDatabase sqLiteDatabase = getReadableAndOpen(databaseHelper);
        Cursor cursor = sqLiteDatabase.query(Diary.TABLE_NAME, null, Diary.ID + "=" + id, null, null, null, null);
        closeTransaction(sqLiteDatabase);
        cursor.moveToFirst();
        Diary diary = convertFromCursor(cursor);
        cursor.close();
        return diary;
    }

    public static void addDiary(Context context, Diary diary){
        DatabaseHelper databaseHelper = new DatabaseHelper(context);
        SQLiteDatabase sqLiteDatabase = getWritableAndOpen(databaseHelper);
        databaseHelper.insert(diary, sqLiteDatabase);
        closeTransaction(sqLiteDatabase);
    }

    public static void updateDiary(Context context, Diary diary){
        DatabaseHelper databaseHelper = new DatabaseHelper(context);
        SQLiteDatabase sqLiteDatabase = getWritableAndOpen(databaseHelper);
        databaseHelper.update(diary, sqLiteDatabase);
        closeTransaction(sqLiteDatabase);
    }

    public static void deleteDiary(Context context, int id){
        DatabaseHelper databaseHelper = new DatabaseHelper(context);
        SQLiteDatabase sqLiteDatabase = getWritableAndOpen(databaseHelper);
        databaseHelper.delete(id, sqLiteDatabase);
        closeTransaction(sqLiteDatabase);
    }

    public static void deleteAllDiary(Context context){
        DatabaseHelper databaseHelper = new DatabaseHelper(context);
        SQLiteDatabase sqLiteDatabase = getWritableAndOpen(databaseHelper);
        databaseHelper.deleteAll(sqLiteDatabase);
        closeTransaction(sqLiteDatabase);
    }

    private static List<Diary> convertCursorToList(Cursor cursor){
        List<Diary> list = new ArrayList<>();
        if(cursor.getCount()!=0){
            cursor.moveToFirst();
            do{
                list.add(convertFromCursor(cursor));
            }while(cursor.moveToNext());
            return list;
        }else{
            return list;
        }


    }

    private static Diary convertFromCursor(Cursor cursor){
        Diary diary = new Diary();

        final int id = cursor.getColumnIndex(Diary.ID);
        final int title = cursor.getColumnIndex(Diary.TITLE);
        final int content = cursor.getColumnIndex(Diary.CONTENT);
        final int location = cursor.getColumnIndex(Diary.LOCATION);
        final int date = cursor.getColumnIndex(Diary.DATE);
        diary.setId(cursor.getInt(id));
        diary.setTitle(cursor.getString(title));
        diary.setContent(cursor.getString(content));
        diary.setLocation(cursor.getString(location));
        diary.setDate(cursor.getString(date));
        return diary;
    }



}

 

Kemudian terdapat package Adapter, ini berhubungan dengan RecyclerView. Isinya terdapat adapter dan viewholder.

DiaryViewHolder.java
package com.andevindo.andevindodiary.Adapter.ViewHolder;

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

import com.andevindo.andevindodiary.Adapter.DiaryAdapter;
import com.andevindo.andevindodiary.Model.Diary;
import com.andevindo.andevindodiary.R;

/**
 * Created by -H- on 10/24/2015.
 */
public class DiaryViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {


    private TextView mTitle, mContent, mLocDate;
    private FloatingActionButton mFab;
    private DiaryAdapter.OnItemClickListener mOnItemClickListener;
    private DiaryAdapter.OnFabClickListener mOnFabClickListener;
    private Diary mDiary;

    public DiaryViewHolder(View itemView, DiaryAdapter.OnItemClickListener onItemClickListener,
                           DiaryAdapter.OnFabClickListener onFabClickListener) {
        super(itemView);
        mOnItemClickListener = onItemClickListener;
        mOnFabClickListener = onFabClickListener;
        mTitle = (TextView) itemView.findViewById(R.id.title);
        mContent = (TextView) itemView.findViewById(R.id.content);
        mLocDate = (TextView) itemView.findViewById(R.id.loc_date);
        mFab = (FloatingActionButton) itemView.findViewById(R.id.fab);
        mFab.setOnClickListener(this);
        itemView.setOnClickListener(this);
    }

    public void setData(Diary diary) {
        mDiary = diary;
        mTitle.setText(diary.getTitle());
        mContent.setText((diary.getContent().length() < 75) ? diary.getContent():diary.getContent().substring(0,74) + "...");
        mLocDate.setText(diary.getLocation() + ", " + diary.getDate());
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.fab) {
            mOnFabClickListener.onFabCliCk(mDiary);
        } else {
            mOnItemClickListener.onItemClick(mDiary);
        }

    }
}

 

DiaryAdapter.java
package com.andevindo.andevindodiary.Adapter;

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

import com.andevindo.andevindodiary.Adapter.ViewHolder.DiaryViewHolder;
import com.andevindo.andevindodiary.Model.Diary;
import com.andevindo.andevindodiary.R;

import java.util.List;

/**
 * Created by -H- on 10/24/2015.
 */
public class DiaryAdapter extends RecyclerView.Adapter<DiaryViewHolder> {

    private List<Diary> mList;
    private Context mContext;
    private OnItemClickListener mOnItemClickListener;
    private OnFabClickListener mOnFabClickListener;

    public DiaryAdapter(List<Diary> list, Context context, OnItemClickListener onItemClickListener, OnFabClickListener onFabClickListener) {
        mList = list;
        mContext = context;
        mOnItemClickListener = onItemClickListener;
        mOnFabClickListener = onFabClickListener;
    }

    public DiaryAdapter(Context context, OnItemClickListener onItemClickListener, OnFabClickListener onFabClickListener) {
        mContext = context;
        mOnItemClickListener = onItemClickListener;
        mOnFabClickListener = onFabClickListener;
    }

    public void setData(List<Diary> list){
        mList = list;
        notifyDataSetChanged();
    }

    @Override
    public DiaryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new DiaryViewHolder(LayoutInflater.from(mContext).inflate(R.layout.custom_list_diary, parent, false), mOnItemClickListener, mOnFabClickListener);
    }

    @Override
    public void onBindViewHolder(DiaryViewHolder holder, int position) {
        holder.setData(mList.get(position));
    }

    @Override
    public int getItemCount() {
        if(mList == null){
            return 0;
        }else{
            return mList.size();
        }

    }

    public interface OnItemClickListener{
        void onItemClick(Diary diary);
    }

    public interface OnFabClickListener{
        void onFabCliCk(Diary diary);
    }
}

 

Yang terakhir adalah package Activity.

DetailActivity.java
package com.andevindo.andevindodiary.Activity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

import com.andevindo.andevindodiary.R;

public class DetailActivity extends AppCompatActivity {

    private TextView mTitle, mContent, mLocDate;

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

        mTitle = (TextView)findViewById(R.id.title);
        mContent = (TextView)findViewById(R.id.content);
        mLocDate = (TextView)findViewById(R.id.loc_date);
        
        //Mendapatkan data dari MainActivity dan ditampilkan dalam TextView;
        mTitle.setText(getIntent().getExtras().getString("title"));
        mContent.setText(getIntent().getExtras().getString("content"));
        mLocDate.setText(getIntent().getExtras().getString("location") + ", " + getIntent().getExtras().getString("date"));
    }
}
DiaryActivity.java
package com.andevindo.andevindodiary.Activity;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;

import com.andevindo.andevindodiary.Database.DiaryHelper;
import com.andevindo.andevindodiary.Model.Diary;
import com.andevindo.andevindodiary.R;
import com.andevindo.andevindodiary.Utils.TimeHelper;

public class DiaryActivity extends AppCompatActivity {

    private EditText mTitle, mContent, mLocation;
    private String mStringTitle, mStringContent, mStringLocation, mStringDate, mStringTag;
    private int mId;
    private CheckBox mUpdateTime;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_diary);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Jika respon yang didapat dari MainActivity adalah untuk membuat diary baru
                if (mStringTag.equals("create")) {
                    create();
                    //Respon untuk update diary
                } else if (mStringTag.equals("update")) {
                    update();
                }
                //Mengembalikan nilai RESULT_OK untuk menandakan bahwa proses sukses
                setResult(RESULT_OK);
                finish();
            }
        });
        mUpdateTime = (CheckBox) findViewById(R.id.update_time);
        mTitle = (EditText) findViewById(R.id.title);
        mContent = (EditText) findViewById(R.id.content);
        mLocation = (EditText) findViewById(R.id.location);
        mStringTag = getIntent().getExtras().getString("tag");
        //Mengatur tampilan untuk kategori update
        if (mStringTag.equals("update")) {
            getSupportActionBar().setTitle("Edit diary");
            mUpdateTime.setVisibility(CheckBox.VISIBLE);
            mId = getIntent().getExtras().getInt("id");
            Log.d("id", mId + "");
            Diary diary = DiaryHelper.getDiary(getApplicationContext(), mId);
            mStringTitle = diary.getTitle();
            mStringContent = diary.getContent();
            mStringLocation = diary.getLocation();
            mStringDate = diary.getDate();
            mTitle.setText(mStringTitle);
            mContent.setText(mStringContent);
            mLocation.setText(mStringLocation);
        } else {
            getSupportActionBar().setTitle("New diary");
            mUpdateTime.setVisibility(CheckBox.GONE);
        }


    }

    //Mendapatkan data dari edittext, lalu update database
    void update() {
        Diary diary = new Diary();
        diary.setId(mId);
        diary.setTitle(mTitle.getText().toString());
        diary.setContent(mContent.getText().toString());
        diary.setLocation(mLocation.getText().toString());
        if (mUpdateTime.isChecked())
            diary.setDate(TimeHelper.getTimeRightNow());
        else
            diary.setDate(mStringDate);
        DiaryHelper.updateDiary(getApplicationContext(), diary);
    }

    //Mendapatkan data dari edittext, lalu create diary baru
    void create() {
        Diary diary = new Diary();
        diary.setTitle(mTitle.getText().toString());
        diary.setContent(mContent.getText().toString());
        diary.setLocation(mLocation.getText().toString());
        diary.setDate(TimeHelper.getTimeRightNow());
        DiaryHelper.addDiary(getApplicationContext(), diary);
    }

    //Menampilkan actionbar menu
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        if (mStringTag.equals("update"))
            inflater.inflate(R.menu.menu_main, menu);
        return true;
    }

    //Respon untuk actionbar menu
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.action_delete) {
            DiaryHelper.deleteDiary(getApplicationContext(), mId);
            setResult(RESULT_OK);
            finish();
            return true;
        } else if (item.getItemId() == android.R.id.home) {
            setResult(RESULT_CANCELED);
            finish();
            return true;
        }
        return false;
    }

}
MainActivity.java
package com.andevindo.andevindodiary.Activity;

import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
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.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;

import com.andevindo.andevindodiary.Adapter.DiaryAdapter;
import com.andevindo.andevindodiary.Database.DiaryHelper;
import com.andevindo.andevindodiary.Model.Diary;
import com.andevindo.andevindodiary.R;

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

public class MainActivity extends AppCompatActivity implements DiaryAdapter.OnItemClickListener, DiaryAdapter.OnFabClickListener {

    private RecyclerView mRecyclerView;
    private DiaryAdapter mDiaryAdapter;
    private List<Diary> mList = 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);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Menggunakan for result karena membutuhkan feedback dari DiaryActivity
                Intent intent = new Intent(MainActivity.this, DiaryActivity.class);
                intent.putExtra("tag", "create");
                startActivityForResult(intent, 100);
            }
        });

        mRecyclerView = (RecyclerView) findViewById(R.id.recycler);
        mDiaryAdapter = new DiaryAdapter(MainActivity.this, this, this);
        mRecyclerView.setAdapter(mDiaryAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
        //Update list dengan asynctask agar tidak mengganggu thread utama
        new LoadDatabase().execute();
    }

    //Sebagai respon dari DiaryActivity
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode==100){
            if(resultCode==RESULT_OK){
                new LoadDatabase().execute();
            }

        }
    }

    //Respon dari fab button yang terdapat dalam item dari recyclerview
    @Override
    public void onFabCliCk(Diary diary) {
        Intent intent = new Intent(MainActivity.this, DiaryActivity.class);
        intent.putExtra("tag", "update");
        intent.putExtra("id", diary.getId());
        startActivityForResult(intent, 100);
    }

    //Respon dari item yang terdapat dalam item dari recyclerview
    @Override
    public void onItemClick(Diary diary) {
        Intent intent = new Intent(MainActivity.this, DetailActivity.class);

        intent.putExtra("title", diary.getTitle());
        intent.putExtra("content", diary.getContent());
        intent.putExtra("location", diary.getLocation());
        intent.putExtra("date", diary.getDate());
        startActivity(intent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if(item.getItemId()==R.id.action_delete){
            DiaryHelper.deleteAllDiary(getApplicationContext());
            mDiaryAdapter.setData(null);
            return true;
        }
        return false;
    }

    //Class untuk update data list
    class LoadDatabase extends AsyncTask<Void, Void ,List<Diary>>{

        @Override
        protected List<Diary> doInBackground(Void... params) {
            return DiaryHelper.getDiaries(MainActivity.this);
        }

        @Override
        protected void onPostExecute(List<Diary> diaries) {
            mDiaryAdapter.setData(diaries);
        }
    }
}
SplashScreenActivity.java
package com.andevindo.andevindodiary.Activity;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;

import com.andevindo.andevindodiary.R;


public class SplashScreenActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash_screen);
        //Menunggu 3 seconds kemudian membuka MainActivity.class
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                startActivity(new Intent(SplashScreenActivity.this, MainActivity.class));
                finish();
            }
        }, 3000);
    }
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.andevindo.andevindodiary" >

    <!-- To auto-complete the email text field in the login form with the user's emails -->
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.READ_PROFILE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".Activity.MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar" >
        </activity>
        <activity
            android:name=".Activity.DiaryActivity"
            android:label="@string/title_activity_diary"
            android:theme="@style/AppTheme.NoActionBar" >
        </activity>
        <activity
            android:name=".Activity.DetailActivity"
            android:theme="@style/AppTheme.Dialog" >
        </activity>
        <activity
            android:name=".Activity.SplashScreenActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.FullScreen" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

 

 

Download Apk

google_play