Membuat Android SQLite Join Multiple Table

Buka kembali tutorial Android SQLite sebelumnya Membuat Android SQLite Sederhana, karena kita akan menggunakannya dan hanya akan menambahkan satu tabel dan beberapa class tambahan untuk memahami konsep join multiple table pada sqlite.
Struktur tabel 1, tabel Karyawan:

Field Type Key Extra
id int Primary Key auto_increment
nama text
gaji double
tgllahir date
bagian int Foreign Key references bagian(id)

Tabel Karyawan diatas merupakan tabel yang kita miliki pada tutorial sebelumnya, dan hanya kita tambahkan field baru yaitu “bagian” sebagai foreign key (kunci tamu)
Struktur tabel 2, tabel Bagian:

Field Type Key Extra
id int Primary Key auto_increment
nama text

Untuk lebih memudahkan dalam memahaminya langsung saja kita praktekan langkah – langkahnya.

Buka kembali project Android SQLite yang sudah kita buat sebelumnya karena kita perlu melakukan penambahan dan beberapa perubahan pada dile yang dibutuhkan.

Buka file strings.xml di direktori res/values/strings.xml ubah isi code menjadi berikut:

res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">AndroidSQLite</string>
    <string name="action_settings">Settings</string>
    <string name="add_kar">Tambah Karyawan</string>
    <string name="update_kar">Update Karyawan</string>
    <string name="nama">Nama Karyawan</string>
    <string name="tgllahir">Tanggal Lahir</string>
    <string name="gaji">Gaji Karyawan</string>
    <string name="update">Update</string>
    <string name="add">Add</string>
    <string name="reset">Reset</string>
    <string name="cancel">Cancel</string>

</resources>

Buka kembali file fragment_add.xml pada direktori res/layout/ dan tambahkan Spinner untuk bagian hingga menjadi code seperti berikut.

res/layout/fragment_add.xml
<?xml version="1.0" encoding="UTF-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
 
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp" >
 
        <EditText
            android:id="@+id/edit_txt_nama"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="@string/nama"
            android:nextFocusDown="@+id/edit_txt_tgllahir"
            android:singleLine="true" />
 
        <EditText
            android:id="@+id/edit_txt_tgllahir"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/edit_txt_nama"
            android:hint="@string/tgllahir"
            android:nextFocusDown="@+id/edit_txt_gaji"
            android:singleLine="true" />
 
        <EditText
            android:id="@+id/edit_txt_gaji"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/edit_txt_tgllahir"
            android:hint="@string/gaji"
            android:inputType="numberDecimal"
            android:singleLine="true" />
        
        <Spinner
            android:id="@+id/spinner_bagian"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/edit_txt_gaji" />
 
        <LinearLayout
            android:id="@+id/layout_submit"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/spinner_bagian"
            android:layout_margin="5dp"
            android:orientation="horizontal"
            android:weightSum="2" >
 
            <Button
                android:id="@+id/button_add"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/add" />
 
            <Button
                android:id="@+id/button_reset"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/reset" />
        </LinearLayout>
    </RelativeLayout>
 
</ScrollView>

File layout diatas akan digunakan untuk class AddFragment yang berfungsi untuk menambahkan data karyawan (nama, tgllahir, gaji, dan nama bagian).

Buka file list_item.xml pada direktori res/layout/ dan tambahkan Texview untuk bagian sehingga code menjadi seperti berikut.

res/layout/list_item.xml
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@color/list_item_bg"
    android:descendantFocusability="blocksDescendants" >
 
    <RelativeLayout
        android:id="@+id/layout_item"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
 
        <TextView
            android:id="@+id/txt_kar_id"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="6dp" />
 
        <TextView
            android:id="@+id/txt_kar_nama"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@+id/txt_kar_id"
            android:padding="6dp" />
 
        <TextView
            android:id="@+id/txt_kar_tgllahir"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/txt_kar_nama"
            android:padding="6dp" />
 
        <TextView
            android:id="@+id/txt_kar_gaji"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/txt_kar_tgllahir"
            android:padding="6dp" />
        
        <TextView
            android:id="@+id/txt_kar_bagian"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/txt_kar_gaji"
            android:padding="6dp"
            android:textColor="#0000FF" />
    </RelativeLayout>
 
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_below="@+id/layout_item"
        android:background="@color/view_divider_color" />
 
</RelativeLayout>

File diatas mendefinisikan tata letak untuk item ListView Karyawan yang digunakan oleh class ListAdapter.

Database SQLite
DataBaseHelper
Pada folder src, buka kembali class DataBaseHelper yang berada di package firman.salatigadev.androidsqlite.db. Class ini akan meng-extends SQLiteOpenHelper yang menangani pembuatan manajemen database dan versi. Kita akan menambahkan tabel Bagian disini.

src/firman.salatigadev.androidsqlite.db/DataBaseHelper.java
package firman.salatigadev.androidsqlite.db;

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

public class DataBaseHelper extends SQLiteOpenHelper {
	
	private static final String DATABASE_NAME = "karyawandb";
    private static final int DATABASE_VERSION = 1;
 
    public static final String TABEL_KARYAWAN = "karyawan";
    public static final String TABEL_BAGIAN = "bagian";
 
    public static final String ID  			 = "id";
    public static final String NAMA 		 = "nama";
    public static final String TANGGAL_LAHIR = "tgllahir";
    public static final String GAJI 		 = "gaji";
    public static final String BAGIAN 	     = "bagian_id";
 
    public static final String CREATE_TABEL_KARYAWAN = "CREATE TABLE "
            + TABEL_KARYAWAN + "(" + ID + " INTEGER PRIMARY KEY, "
            + NAMA + " TEXT, " + GAJI + " DOUBLE, "
            + TANGGAL_LAHIR + " DATE, " + BAGIAN + " INT, " + "FOREIGN KEY(" + BAGIAN + ") REFERENCES "
            + TABEL_BAGIAN + "(id) " + ")";
    
    public static final String CREATE_TABEL_BAGIAN = "CREATE TABLE "
            + TABEL_BAGIAN + "(" + ID + " INTEGER PRIMARY KEY,"
            + NAMA + ")";
    
    private static DataBaseHelper instance;
 
    public static synchronized DataBaseHelper getHelper(Context context) {
        if (instance == null)
            instance = new DataBaseHelper(context);
        return instance;
    }
 
    private DataBaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
    
    @Override
    public void onOpen(SQLiteDatabase db) {
        super.onOpen(db);
        if (!db.isReadOnly()) {
            // Enable foreign key constraints
            db.execSQL("PRAGMA foreign_keys=ON;");
        }
    }
 
    @Override
    public void onCreate(SQLiteDatabase db) {
    	db.execSQL(CREATE_TABEL_BAGIAN);
        db.execSQL(CREATE_TABEL_KARYAWAN);
    }
 
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}

Memasukan Record Baru (Bagian) Pada Database SQLite
Bagian
Dalam folder src, buat class Bagian pada package firman.salatigadev.androidsqlite.to. Class ini merepresentasikan tabel bagian dalam database.

src/firman.salatigadev.androidsqlite.to/Bagian.java
package firman.salatigadev.androidsqlite.to;

import android.os.Parcel;
import android.os.Parcelable;

public class Bagian implements Parcelable {
	
	private int id;
    private String nama;
 
    public Bagian() {
        super();
    }
 
    public Bagian(int id, String nama) {
        super();
        this.id = id;
        this.nama = nama;
    }
 
    public Bagian(String nama) {
        this.nama = nama;
    }
 
    private Bagian(Parcel in) {
        super();
        this.id = in.readInt();
        this.nama = in.readString();
    }
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getNama() {
        return nama;
    }
 
    public void setNama(String nama) {
        this.nama = nama;
    }
 
    @Override
    public String toString() {
        return "id:" + id + ", nama:" + nama;
    }
 
    @Override
    public int describeContents() {
        return 0;
    }
 
    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeInt(getId());
        parcel.writeString(getNama());
    }
 
    public static final Parcelable.Creator<Bagian> CREATOR = new Parcelable.Creator<Bagian>() {
        public Bagian createFromParcel(Parcel in) {
            return new Bagian(in);
        }
 
        public Bagian[] newArray(int size) {
            return new Bagian[size];
        }
    };
 
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        return result;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Bagian other = (Bagian) obj;
        if (id != other.id)
            return false;
        return true;
    }

}

Karyawan
Buka kembali class Karyawan pada package yang sama. Class ini merepresentasikan karyawan untuk disimpan dalam database dan class ini memiliki objek yang mendefinisikan bagian sebagai Foreign Key(kunci tamu).

src/firman.salatigadev.androidsqlite.to/Karyawan.java
package firman.salatigadev.androidsqlite.to;

import java.util.Date;
import android.os.Parcel;
import android.os.Parcelable;

public class Karyawan implements Parcelable {
	
	private int id;
    private String nama;
    private Date tanggal_lahir;
    private double gaji;
    
    private Bagian bagian;
 
    public Karyawan() {
        super();
    }
 
    private Karyawan(Parcel in) {
        super();
        this.id = in.readInt();
        this.nama = in.readString();
        this.tanggal_lahir = new Date(in.readLong());
        this.gaji = in.readDouble();
        
        this.bagian = in.readParcelable(Bagian.class.getClassLoader());
    }
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getNama() {
        return nama;
    }
 
    public void setNama(String nama) {
        this.nama = nama;
    }
 
    public Date getTanggalLahir() {
        return tanggal_lahir;
    }
 
    public void setTanggalLahir(Date tanggal_lahir) {
        this.tanggal_lahir = tanggal_lahir;
    }
 
    public double getGaji() {
        return gaji;
    }
 
    public void setGaji(double gaji) {
        this.gaji = gaji;
    }
    
    public Bagian getBagian() {
        return bagian;
    }
 
    public void setBagian(Bagian bagian) {
        this.bagian = bagian;
    }
 
    @Override
    public String toString() {
        return "Karyawan [id=" + id + ", nama=" + nama + ", tanggal_lahir="
                + tanggal_lahir + ", gaji=" + gaji + ", bagian="
                + bagian + "]";
    }
 
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        return result;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Karyawan other = (Karyawan) obj;
        if (id != other.id)
            return false;
        return true;
    }
 
    @Override
    public int describeContents() {
        return 0;
    }
 
    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeInt(getId());
        parcel.writeString(getNama());
        parcel.writeLong(getTanggalLahir().getTime());
        parcel.writeDouble(getGaji());
        parcel.writeParcelable(getBagian(), flags);
    }
 
    public static final Parcelable.Creator<Karyawan> CREATOR = new Parcelable.Creator<Karyawan>() {
        public Karyawan createFromParcel(Parcel in) {
            return new Karyawan(in);
        }
 
        public Karyawan[] newArray(int size) {
            return new Karyawan[size];
        }
    };
    
}

BagianDAO
Buat class BagianDAO di folder src dalam package firman.salatigadev.androidsqlite.db. Class ini meluaskan class KaryawanDBDAO dan mengimplementasikan operasi database seperti mengambil, menyimpan, update, dan menghapus pada objek bagian. Method loadBagians() akan memuat record ke dalam tabel Bagian.

src/firman.salatigadev.androidsqlite.db/BagianDAO.java
package firman.salatigadev.androidsqlite.db;

import java.util.ArrayList;
import java.util.List;
 
import firman.salatigadev.androidsqlite.to.Bagian;
 
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;

public class BagianDAO extends KaryawanDBDAO {
	private static final String WHERE_ID_EQUALS = DataBaseHelper.ID
            + " =?";
 
    public BagianDAO(Context context) {
        super(context);
    }
 
    public long save(Bagian bagian) {
        ContentValues values = new ContentValues();
        values.put(DataBaseHelper.NAMA, bagian.getNama());
 
        return database.insert(DataBaseHelper.TABEL_BAGIAN, null, values);
    }
 
    public long update(Bagian bagian) {
        ContentValues values = new ContentValues();
        values.put(DataBaseHelper.NAMA, bagian.getNama());
 
        long result = database.update(DataBaseHelper.TABEL_BAGIAN, values,
                WHERE_ID_EQUALS,
                new String[] { String.valueOf(bagian.getId()) });
        Log.d("Hasil Update:", "=" + result);
        return result;
 
    }
 
    public int deleteBag(Bagian bagian) {
        return database.delete(DataBaseHelper.TABEL_BAGIAN,
                WHERE_ID_EQUALS, new String[] { bagian.getId() + "" });
    }
 
    public List<Bagian> getBagians() {
        List<Bagian> bagians = new ArrayList<Bagian>();
        Cursor cursor = database.query(DataBaseHelper.TABEL_BAGIAN,
                new String[] { DataBaseHelper.ID,
                        DataBaseHelper.NAMA }, null, null, null, null,
                null);
 
        while (cursor.moveToNext()) {
        	Bagian bagian = new Bagian();
        	bagian.setId(cursor.getInt(0));
        	bagian.setNama(cursor.getString(1));
        	bagians.add(bagian);
        }
        return bagians;
    }
 
    public void loadBagians() {
    	Bagian bagian = new Bagian("Development");
    	Bagian bagian1 = new Bagian("HRD");
    	Bagian bagian2 = new Bagian("IT");
    	Bagian bagian3 = new Bagian("Admin");
        Bagian bagian4 = new Bagian("Marketing");
        Bagian bagian5 = new Bagian("Sales");
 
        List<Bagian> bagians = new ArrayList<Bagian>();
        bagians.add(bagian);
        bagians.add(bagian1);
        bagians.add(bagian2);
        bagians.add(bagian3);
        bagians.add(bagian4);
        bagians.add(bagian5);
        for (Bagian bag : bagians) {
            ContentValues values = new ContentValues();
            values.put(DataBaseHelper.NAMA, bag.getNama());
            database.insert(DataBaseHelper.TABEL_BAGIAN, null, values);
        }
    }
}

KaryawanDAO
Buka kembali class KaryawanDAO pada package yang sama dan ubah code menjadi seperti berikut.

src/firman.salatigadev.androidsqlite.db/KaryawanDAO.java
package firman.salatigadev.androidsqlite.db;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Locale;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;

import firman.salatigadev.androidsqlite.to.Bagian;
import firman.salatigadev.androidsqlite.to.Karyawan;

public class KaryawanDAO extends KaryawanDBDAO {
	public static final String KARYAWAN_ID = "kar.id";
    public static final String KARYAWAN_NAMA = "kar.nama";
    public static final String BAGIAN_NAMA = "bag.nama";
	
	private static final String WHERE_ID_EQUALS = DataBaseHelper.ID
			+ " =?";
	private static final SimpleDateFormat formatter = new SimpleDateFormat(
			"yyyy-MM-dd", Locale.ENGLISH);

	public KaryawanDAO(Context context) {
		super(context);
	}

	public long save(Karyawan karyawan) {
		ContentValues values = new ContentValues();
		values.put(DataBaseHelper.NAMA, karyawan.getNama());
		Log.d("tgllahir", karyawan.getTanggalLahir().getTime() + "");
		values.put(DataBaseHelper.TANGGAL_LAHIR, formatter.format(karyawan.getTanggalLahir()));
		values.put(DataBaseHelper.GAJI, karyawan.getGaji());
		values.put(DataBaseHelper.BAGIAN, karyawan.getBagian().getId());

		return database.insert(DataBaseHelper.TABEL_KARYAWAN, null, values);
	}

	public long update(Karyawan karyawan) {
		ContentValues values = new ContentValues();
		values.put(DataBaseHelper.NAMA, karyawan.getNama());
		values.put(DataBaseHelper.TANGGAL_LAHIR, formatter.format(karyawan.getTanggalLahir()));
		values.put(DataBaseHelper.GAJI, karyawan.getGaji());
		values.put(DataBaseHelper.BAGIAN, karyawan.getBagian().getId());

		long result = database.update(DataBaseHelper.TABEL_KARYAWAN, values,
				WHERE_ID_EQUALS,
				new String[] { String.valueOf(karyawan.getId()) });
		Log.d("Hasil Update :", "=" + result);
		return result;

	}

	public int delete(Karyawan karyawan) {
		return database.delete(DataBaseHelper.TABEL_KARYAWAN, WHERE_ID_EQUALS,
				new String[] { karyawan.getId() + "" });
	}

	public ArrayList<Karyawan> getKaryawans() {
		ArrayList<Karyawan> karyawans = new ArrayList<Karyawan>();
		String query = "SELECT " + KARYAWAN_ID + ","
				+ KARYAWAN_NAMA + "," + DataBaseHelper.TANGGAL_LAHIR
				+ "," + DataBaseHelper.GAJI + ","
				+ DataBaseHelper.BAGIAN + ","
				+ BAGIAN_NAMA + " FROM "
				+ DataBaseHelper.TABEL_KARYAWAN + " kar, "
				+ DataBaseHelper.TABEL_BAGIAN + " bag WHERE kar."
				+ DataBaseHelper.BAGIAN + " = bag."
				+ DataBaseHelper.ID;

		// Building query using INNER JOIN keyword
		/*String query = "SELECT " + EMPLOYEE_ID_WITH_PREFIX + ","
		+ EMPLOYEE_NAME_WITH_PREFIX + "," + DataBaseHelper.EMPLOYEE_DOB
		+ "," + DataBaseHelper.EMPLOYEE_SALARY + ","
		+ DataBaseHelper.EMPLOYEE_DEPARTMENT_ID + ","
		+ DEPT_NAME_WITH_PREFIX + " FROM "
		+ DataBaseHelper.EMPLOYEE_TABLE + " emp INNER JOIN "
		+ DataBaseHelper.DEPARTMENT_TABLE + " dept ON emp."
		+ DataBaseHelper.EMPLOYEE_DEPARTMENT_ID + " = dept."
		+ DataBaseHelper.ID_COLUMN;*/

		Log.d("query", query);
		Cursor cursor = database.rawQuery(query, null);
		while (cursor.moveToNext()) {
			Karyawan karyawan = new Karyawan();
			karyawan.setId(cursor.getInt(0));
			karyawan.setNama(cursor.getString(1));
			try {
				karyawan.setTanggalLahir(formatter.parse(cursor.getString(2)));
			} catch (ParseException e) {
				karyawan.setTanggalLahir(null);
			}
			karyawan.setGaji(cursor.getDouble(3));

			Bagian bagian = new Bagian();
			bagian.setId(cursor.getInt(4));
			bagian.setNama(cursor.getString(5));

			karyawan.setBagian(bagian);

			karyawans.add(karyawan);
		}
		return karyawans;
	}		
	
	/*
	//Mengambil satu record karyawan dengan id yang diberikan
	public Karyawan getKaryawan(long id) {
		Karyawan karyawan = null;

		String sql = "SELECT * FROM " + DataBaseHelper.TABEL_KARYAWAN
				+ " WHERE " + DataBaseHelper.ID + " = ?";

		Cursor cursor = database.rawQuery(sql, new String[] { id + "" });

		if (cursor.moveToNext()) {
			karyawan = new Karyawan();
			karyawan.setId(cursor.getInt(0));
			karyawan.setNama(cursor.getString(1));
			try {
				karyawan.setTanggalLahir(formatter.parse(cursor.getString(2)));
			} catch (ParseException e) {
				karyawan.setTanggalLahir(null);
			}
			karyawan.setGaji(cursor.getDouble(3));
		}
		return karyawan;
	} */
}

AddFragment
Buka class AddFragment dalam folder src di package firman.salatigadev.androidsqlite.fragment. Fragment ini menampilkan form untuk memasukkan data karyawan seperti nama, tanggal lahir, gaji, dan bagian(sebagai Spinner).

src/firman.salatigadev.androidsqlite.fragment/AddFragment.java
package firman.salatigadev.androidsqlite.fragment;

import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
 
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.InputType;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
 
import firman.salatigadev.androidsqlite.R;
import firman.salatigadev.androidsqlite.db.BagianDAO;
import firman.salatigadev.androidsqlite.db.KaryawanDAO;
import firman.salatigadev.androidsqlite.to.Bagian;
import firman.salatigadev.androidsqlite.to.Karyawan;

public class AddFragment extends Fragment implements OnClickListener {
	
	 //referensi form
    private EditText namaEtxt;
    private EditText gajiEtxt;
    private EditText tgllahirEtxt;
    private Spinner bagSpinner;
    private Button addButton;
    private Button resetButton;
 
    private static final SimpleDateFormat formatter = new SimpleDateFormat(
            "yyyy-MM-dd", Locale.ENGLISH);
 
    DatePickerDialog datePickerDialog;
    Calendar dateCalendar;
 
    Karyawan karyawan = null;
    private BagianDAO bagianDAO;
    private KaryawanDAO karyawanDAO;
    private GetBagTask task;
    private AddKarTask addTask;
 
    public static final String ARG_ITEM_ID = "add_fragment";
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        karyawanDAO = new KaryawanDAO(getActivity());
        bagianDAO = new BagianDAO(getActivity());
    }
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_add, container,
                false);
 
        findViewsById(rootView);
 
        setListeners();
 
        if (savedInstanceState != null) {
            dateCalendar = Calendar.getInstance();
            if (savedInstanceState.getLong("dateCalendar") != 0)
                dateCalendar.setTime(new Date(savedInstanceState
                        .getLong("dateCalendar")));
        }
        
        task = new GetBagTask(getActivity());
        task.execute((Void) null);
 
        return rootView;
    }
 
    private void setListeners() {
    	tgllahirEtxt.setOnClickListener(this);
        Calendar newCalendar = Calendar.getInstance();
        datePickerDialog = new DatePickerDialog(getActivity(),
                new OnDateSetListener() {
 
                    public void onDateSet(DatePicker view, int year,
                            int monthOfYear, int dayOfMonth) {
                        dateCalendar = Calendar.getInstance();
                        dateCalendar.set(year, monthOfYear, dayOfMonth);
                        tgllahirEtxt.setText(formatter.format(dateCalendar
                                .getTime()));
                    }
 
                }, newCalendar.get(Calendar.YEAR),
                newCalendar.get(Calendar.MONTH),
                newCalendar.get(Calendar.DAY_OF_MONTH));
 
        addButton.setOnClickListener(this);
        resetButton.setOnClickListener(this);
    }
 
    protected void resetAllFields() {
    	namaEtxt.setText("");
    	gajiEtxt.setText("");
        tgllahirEtxt.setText("");
        if (bagSpinner.getAdapter().getCount() > 0)
            bagSpinner.setSelection(0);
    }
 
    private void setKaryawan() {
    	karyawan = new Karyawan();
    	karyawan.setNama(namaEtxt.getText().toString());
    	karyawan.setGaji(Double.parseDouble(gajiEtxt.getText()
                .toString()));
        if (dateCalendar != null)
        	karyawan.setTanggalLahir(dateCalendar.getTime());
        Bagian selectedBag = (Bagian) bagSpinner.getSelectedItem();
        karyawan.setBagian(selectedBag);
    }
 
    @Override
    public void onResume() {
        getActivity().setTitle(R.string.add_kar);
        getActivity().getActionBar().setTitle(R.string.add_kar);
        super.onResume();
    }
 
    @Override
    public void onSaveInstanceState(Bundle outState) {
        if (dateCalendar != null)
            outState.putLong("dateCalendar", dateCalendar.getTime().getTime());
    }
 
    private void findViewsById(View rootView) {
    	namaEtxt = (EditText) rootView.findViewById(R.id.edit_txt_nama);
    	gajiEtxt = (EditText) rootView.findViewById(R.id.edit_txt_gaji);
    	tgllahirEtxt = (EditText) rootView.findViewById(R.id.edit_txt_tgllahir);
    	tgllahirEtxt.setInputType(InputType.TYPE_NULL);
 
    	bagSpinner = (Spinner) rootView.findViewById(R.id.spinner_bagian);
    	addButton = (Button) rootView.findViewById(R.id.button_add);
        resetButton = (Button) rootView.findViewById(R.id.button_reset);
    }
 
    @Override
    public void onClick(View view) {
        if (view == tgllahirEtxt) {
            datePickerDialog.show();
        } else if (view == addButton) {
            setKaryawan();
 
            addTask = new AddKarTask(getActivity());
            addTask.execute((Void) null);
        } else if (view == resetButton) {
            resetAllFields();
        }
    }
    
    public class GetBagTask extends AsyncTask<Void, Void, Void> {
    	 
        private final WeakReference<Activity> activityWeakRef;
        private List<Bagian> bagians;
 
        public GetBagTask(Activity context) {
            this.activityWeakRef = new WeakReference<Activity>(context);
        }
 
        @Override
        protected Void doInBackground(Void... arg0) {
        	bagians = bagianDAO.getBagians();
            return null;
        }
 
        @Override
        protected void onPostExecute(Void v) {
            if (activityWeakRef.get() != null
                    && !activityWeakRef.get().isFinishing()) {
 
                ArrayAdapter<Bagian> adapter = new ArrayAdapter<Bagian>(
                        activityWeakRef.get(),
                        android.R.layout.simple_list_item_1, bagians);
                bagSpinner.setAdapter(adapter);
 
                addButton.setEnabled(true);
            }
        }
    }
 
    public class AddKarTask extends AsyncTask<Void, Void, Long> {
 
        private final WeakReference<Activity> activityWeakRef;
 
        public AddKarTask(Activity context) {
            this.activityWeakRef = new WeakReference<Activity>(context);
        }
 
        @Override
        protected Long doInBackground(Void... arg0) {
            long result = karyawanDAO.save(karyawan);
            return result;
        }
 
        @Override
        protected void onPostExecute(Long result) {
            if (activityWeakRef.get() != null
                    && !activityWeakRef.get().isFinishing()) {
                if (result != -1)
                    Toast.makeText(activityWeakRef.get(), "Simpan Karyawan",
                            Toast.LENGTH_LONG).show();
            }
        }
    }
}

ListAdapter
Buka kembali class ListAdapter di folder src baru dalam package firman.salatigadev.androidsqlite.adapter dan ubah menjadi seperti code berikut. Ini adalah custom list yang menampilkan data karyawan (id, nama, tanggal lahir, gaji, dan nama bagian).

src/irman.salatigadev.androidsqlite.adapter/ListAdapter.java
package firman.salatigadev.androidsqlite.adapter;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
 
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
 
import firman.salatigadev.androidsqlite.R;
import firman.salatigadev.androidsqlite.to.Karyawan;

public class ListAdapter extends ArrayAdapter<Karyawan> {
	
	private Context context;
    List<Karyawan> karyawans;
 
    private static final SimpleDateFormat formatter = new SimpleDateFormat(
            "yyyy-MM-dd", Locale.ENGLISH);
 
    public ListAdapter(Context context, List<Karyawan> karyawans) {
        super(context, R.layout.list_item, karyawans);
        this.context = context;
        this.karyawans = karyawans;
    }
 
    private class ViewHolder {
        TextView idTxt;
        TextView namaTxt;
        TextView tgllahirTxt;
        TextView gajiTxt;
        TextView bagNamaTxt;
    }
 
    @Override
    public int getCount() {
        return karyawans.size();
    }
 
    @Override
    public Karyawan getItem(int position) {
        return karyawans.get(position);
    }
 
    @Override
    public long getItemId(int position) {
        return 0;
    }
 
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.list_item, null);
            holder = new ViewHolder();
 
            holder.idTxt = (TextView) convertView
                    .findViewById(R.id.txt_kar_id);
            holder.namaTxt = (TextView) convertView
                    .findViewById(R.id.txt_kar_nama);
            holder.tgllahirTxt = (TextView) convertView
                    .findViewById(R.id.txt_kar_tgllahir);
            holder.gajiTxt = (TextView) convertView
                    .findViewById(R.id.txt_kar_gaji);
            holder.bagNamaTxt = (TextView) convertView
                    .findViewById(R.id.txt_kar_bagian);
 
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        Karyawan karyawan = (Karyawan) getItem(position);
        holder.idTxt.setText(karyawan.getId() + "");
        holder.namaTxt.setText(karyawan.getNama());
        holder.gajiTxt.setText(karyawan.getGaji() + "");
        holder.bagNamaTxt.setText(karyawan.getBagian().getNama());
 
        holder.tgllahirTxt.setText(formatter.format(karyawan.getTanggalLahir()));
 
        return convertView;
    }
 
    @Override
    public void add(Karyawan karyawan) {
    	karyawans.add(karyawan);
        notifyDataSetChanged();
        super.add(karyawan);
    }
 
    @Override
    public void remove(Karyawan karyawan) {
    	karyawans.remove(karyawan);
        notifyDataSetChanged();
        super.remove(karyawan);
    }
    
}

CustomDialogFragment
Buka kembali class CustomDialogFragment pada folder src dalam package firman.salatigadev.androidsqlite.fragment dan ubah seperti contoh berikut. Class akan menerima obyek karyawan dan menampilkan dialog dengan rincian update data karyawan (nama, tgl lahir, gaji, dan nama bagian). Jika update berhasil, maka akan memanggil method onFinishDialog() pada MainActivity untuk memberitahu ListView(ListFragment).

src/firman.salatigadev.androidsqlite.fragment/CustomDialogFragment.java
package firman.salatigadev.androidsqlite.fragment;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
 
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.Toast;
 
import firman.salatigadev.androidsqlite.MainActivity;
import firman.salatigadev.androidsqlite.R;
import firman.salatigadev.androidsqlite.db.BagianDAO;
import firman.salatigadev.androidsqlite.db.KaryawanDAO;
import firman.salatigadev.androidsqlite.to.Bagian;
import firman.salatigadev.androidsqlite.to.Karyawan;

public class CustomDialogFragment extends DialogFragment {
	
	//referensi form
    private EditText namaEtxt;
    private EditText gajiEtxt;
    private EditText tgllahirEtxt;
    private Spinner bagSpinner;
    private LinearLayout submitLayout;
 
    private Karyawan karyawan;
 
    private static final SimpleDateFormat formatter = new SimpleDateFormat(
            "yyyy-MM-dd", Locale.ENGLISH);
    
    KaryawanDAO karyawanDAO;
    ArrayAdapter<Bagian> adapter;
    
    public static final String ARG_ITEM_ID = "emp_dialog_fragment";
 
    public interface DialogFragmentListener {
        void onFinishDialog();
    }
 
    public CustomDialogFragment() {
 
    }
 
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
    	karyawanDAO = new KaryawanDAO(getActivity());
 
        Bundle bundle = this.getArguments();
        karyawan = bundle.getParcelable("selectedKaryawan");
 
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        LayoutInflater inflater = getActivity().getLayoutInflater();
 
        View customDialogView = inflater.inflate(R.layout.fragment_add, null);
        builder.setView(customDialogView);
 
        namaEtxt = (EditText) customDialogView.findViewById(R.id.edit_txt_nama);
        gajiEtxt = (EditText) customDialogView
                .findViewById(R.id.edit_txt_gaji);
        tgllahirEtxt = (EditText) customDialogView.findViewById(R.id.edit_txt_tgllahir);
        bagSpinner = (Spinner) customDialogView
                .findViewById(R.id.spinner_bagian);
        submitLayout = (LinearLayout) customDialogView
                .findViewById(R.id.layout_submit);
        submitLayout.setVisibility(View.GONE);
 
        setValue();
 
        builder.setTitle(R.string.update_kar);
        builder.setCancelable(false);
        builder.setPositiveButton(R.string.update,
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        try {
                        	karyawan.setTanggalLahir(formatter.parse(tgllahirEtxt.getText().toString()));
                        } catch (ParseException e) {
                            Toast.makeText(getActivity(),
                                    "Format data tidak valid!",
                                    Toast.LENGTH_SHORT).show();
                            return;
                        }
                        karyawan.setNama(namaEtxt.getText().toString());
                        karyawan.setGaji(Double.parseDouble(gajiEtxt
                                .getText().toString()));
                        Bagian bag = (Bagian) adapter
                                .getItem(bagSpinner.getSelectedItemPosition());
                        karyawan.setBagian(bag);
                        long result = karyawanDAO.update(karyawan);
                        if (result > 0) {
                            MainActivity activity = (MainActivity) getActivity();
                            activity.onFinishDialog();
                        } else {
                            Toast.makeText(getActivity(),
                                    "Tidak bisa update karyawan",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                });
        builder.setNegativeButton(R.string.cancel,
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                    }
                });
 
        AlertDialog alertDialog = builder.create();
 
        return alertDialog;
    }
 
    private void setValue() {
    	BagianDAO bagianDAO = new BagianDAO(getActivity());
    	 
        List<Bagian> bagians = bagianDAO.getBagians();
        adapter = new ArrayAdapter<Bagian>(getActivity(),
                android.R.layout.simple_list_item_1, bagians);
        bagSpinner.setAdapter(adapter);
        int pos = adapter.getPosition(karyawan.getBagian());
        
        if (karyawan != null) {
        	namaEtxt.setText(karyawan.getNama());
        	gajiEtxt.setText(karyawan.getGaji() + "");
        	tgllahirEtxt.setText(formatter.format(karyawan.getTanggalLahir()));
        	bagSpinner.setSelection(pos);
        }
    }
}

MainActivity
Class MainActivity adalah class utama ketika aplikasi dijalankan, kita tambahkan ListFragment. Activity ini akan menangani method onBackPressed() dan akan menunjukkan dialog peringatan ketika ingin berhenti/keluar aplikasi.

src/firman.salatigadev.androidsqlite/MainActivity.java
package firman.salatigadev.androidsqlite;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
import android.view.MenuItem;
 
import firman.salatigadev.androidsqlite.db.BagianDAO;
import firman.salatigadev.androidsqlite.fragment.CustomDialogFragment.DialogFragmentListener;
import firman.salatigadev.androidsqlite.fragment.AddFragment;
import firman.salatigadev.androidsqlite.fragment.ListFragment;

public class MainActivity extends FragmentActivity implements DialogFragmentListener {
	
	private Fragment contentFragment;
    private ListFragment karyawanListFragment;
    private AddFragment karyawanAddFragment;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		FragmentManager fragmentManager = getSupportFragmentManager();
		BagianDAO bagDAO = new BagianDAO(this);
		
		//bagians
        if(bagDAO.getBagians().size() <= 0)
            bagDAO.loadDepartments();
		
		/*
         * This is called when orientation is changed.
         */
        if (savedInstanceState != null) {
            if (savedInstanceState.containsKey("content")) {
                String content = savedInstanceState.getString("content");
                if (content.equals(AddFragment.ARG_ITEM_ID)) {
                    if (fragmentManager
                            .findFragmentByTag(AddFragment.ARG_ITEM_ID) != null) {
                        setFragmentTitle(R.string.add_kar);
                        contentFragment = fragmentManager
                                .findFragmentByTag(AddFragment.ARG_ITEM_ID);
                    }
                }
            }
            if (fragmentManager.findFragmentByTag(ListFragment.ARG_ITEM_ID) != null) {
                karyawanListFragment = (ListFragment) fragmentManager
                        .findFragmentByTag(ListFragment.ARG_ITEM_ID);
                contentFragment = karyawanListFragment;
            }
        } else {
        	karyawanListFragment = new ListFragment();
            setFragmentTitle(R.string.app_name);
            switchContent(karyawanListFragment, ListFragment.ARG_ITEM_ID);
        }
    }
 
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        if (contentFragment instanceof AddFragment) {
            outState.putString("content", AddFragment.ARG_ITEM_ID);
        } else {
            outState.putString("content", ListFragment.ARG_ITEM_ID);
        }
        super.onSaveInstanceState(outState);
    }

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_add:
            setFragmentTitle(R.string.add_kar);
            karyawanAddFragment = new AddFragment();
            switchContent(karyawanAddFragment, AddFragment.ARG_ITEM_ID);
 
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
 
    /*
     * We consider EmpListFragment as the home fragment and it is not added to
     * the back stack.
     */
    public void switchContent(Fragment fragment, String tag) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        while (fragmentManager.popBackStackImmediate())
            ;
 
        if (fragment != null) {
            FragmentTransaction transaction = fragmentManager
                    .beginTransaction();
            transaction.replace(R.id.content_frame, fragment, tag);
            
            if (!(fragment instanceof ListFragment)) {
                transaction.addToBackStack(tag);
            }
            transaction.commit();
            contentFragment = fragment;
        }
    }
 
    protected void setFragmentTitle(int resourseId) {
        setTitle(resourseId);
        getActionBar().setTitle(resourseId);
 
    }
 
    /*
     * We call super.onBackPressed(); when the stack entry count is > 0. if it
     * is instanceof EmpListFragment or if the stack entry count is == 0, then
     * we prompt the user whether to quit the app or not by displaying dialog.
     * In other words, from EmpListFragment on back press it quits the app.
     */
    @Override
    public void onBackPressed() {
        FragmentManager fm = getSupportFragmentManager();
        if (fm.getBackStackEntryCount() > 0) {
            super.onBackPressed();
        } else if (contentFragment instanceof ListFragment
                || fm.getBackStackEntryCount() == 0) {
            //tampilkan dialog ketika keluar
            onShowQuitDialog();
        }
    }
 
    public void onShowQuitDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setCancelable(false);
 
        builder.setMessage("Anda Ingin Keluar?");
        builder.setPositiveButton(android.R.string.yes,
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        finish();
                    }
                });
        builder.setNegativeButton(android.R.string.no,
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                    }
                });
        builder.create().show();
    }
 
    @Override
    public void onFinishDialog() {
        if (karyawanListFragment != null) {
        	karyawanListFragment.updateView();
        }
    }
}

Running aplikasi.
                     

You may also like...

1 Response

  1. Your style is really unique compared to other folks
    I’ve read stuff from. Many thanks for posting when you have
    the opportunity, Guess I will just book mark this blog.

Leave a Reply

Your email address will not be published. Required fields are marked *