Membuat aplikasi menggunakan Kotlin dan Java – Bagian 2

Photo by Arnold Francisca on Unsplash

Melanjutkan artikel bagian 1 yang sebelumnya merupakan bagian pembuatan layout untuk membuat aplikasi sederhana mengkombinasikan Java dan Kotlin. nah, pada bagian ini kita fokus pada bagian kode.

Pertama buat package models, letakkan didalam package com.dekikurnia.belajarkotlin. Kemudian, buat class Java dengan nama Item. pada class ini kita buat 3 buah variabel yaitu id, title dan description. variabel id kita gunakan sebagai kunci utama (primary key).  Berikut kodenya :

Item.java :
package com.dekikurnia.belajarkotlin.models;
 
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
 
public class Item extends RealmObject {
    @PrimaryKey
    private String id;
    private String title;
    private String description;
 
 
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getTitle() {
        return title;
    }
 
    public void setTitle(String title) {
        this.title = title;
    }
 
    public String getDescription() {
        return description;
    }
 
    public void setDescription(String description) {
        this.description = description;
    }
}

Setelah membuat model, selanjutnya adalah membuat adapter untuk menyiapkan layout dan mengatur bagaimana item akan ditampilkan di RecyclerView. Buat class Java dengan nama ItemAdapter didalam package com.dekikurnia.belajarkotlin

ItemAdapter.java :
package com.dekikurnia.belajarkotlin;
 
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.dekikurnia.belajarkotlin.models.Item;
import butterknife.Bind;
import butterknife.ButterKnife;
import io.realm.RealmBasedRecyclerViewAdapter;
import io.realm.RealmResults;
import io.realm.RealmViewHolder;
 
public class ItemAdapter extends RealmBasedRecyclerViewAdapter<Item, ItemAdapter.ViewHolder> {
 
    private ItemClickListener clickListener;
 
    public ItemAdapter(Context context, RealmResults<Item> realmResults, boolean automaticUpdate,
                       boolean animateResults, ItemClickListener clickListener) {
        super(context, realmResults, automaticUpdate, animateResults);
        this.clickListener = clickListener;
    }
 
    @Override
    public ViewHolder onCreateRealmViewHolder(ViewGroup viewGroup, int i) {
        View v = inflater.inflate(R.layout.crud_item, viewGroup, false);
        return new ViewHolder(v, clickListener);
    }
 
    @Override
    public void onBindRealmViewHolder(ViewHolder viewHolder, int i) {
        final Item item = realmResults.get(i);
        viewHolder.ItemTitle.setText(item.getTitle());
    }
 
    class ViewHolder extends RealmViewHolder implements View.OnClickListener {
        @Bind(R.id.crud_item_title) public TextView ItemTitle;
        private ItemClickListener clickListener;
 
        public ViewHolder(View itemView, ItemClickListener clickListener) {
            super(itemView);
            this.clickListener = clickListener;
            ButterKnife.bind(this, itemView);
            itemView.setOnClickListener(this);
        }
 
        @Override
        public void onClick(View v) {
            if(clickListener != null) {
                clickListener.onItemClick(v, realmResults.get(getAdapterPosition()));
            }
        }
    }
 
    public interface ItemClickListener {
        void onItemClick(View caller, Item task);
    }
}

Setelah membuat kode untuk adapter, selanjutnya ada membuat kode untuk fragment. Fragment ini mengimplementasikan  method ItemAdapter.ItemClickListener  kemudian implement all abstract method tadi. Setelah itu akan muncul method onItemClick. Pada method onItemClick inilah, item yang tampil ketika diklik akan memanggil class EditFragment sekaligus menyembunyikan FloatingActionButton.

ItemFragment.java :
package com.dekikurnia.belajarkotlin;
 
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
import com.dekikurnia.belajarkotlin.models.Item;
 
import butterknife.Bind;
import butterknife.ButterKnife;
import co.moonmonkeylabs.realmrecyclerview.RealmRecyclerView;
import io.realm.Realm;
import io.realm.RealmResults;
 
public class ItemFragment extends Fragment implements ItemAdapter.ItemClickListener {
    @Bind(R.id.crud_recycler_view) protected RealmRecyclerView rv;
    private Realm realm;
 
    public static ItemFragment newInstance() {
        return new ItemFragment();
    }
 
    public ItemFragment() {
    }
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_crud, container, false);
        ButterKnife.bind(this, v);
        return v;
    }
 
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        realm = Realm.getDefaultInstance();
 
    }
 
    @Override
    public void onResume() {
        super.onResume();
        RealmResults<Item> todos = realm.where(Item.class).findAll();
        ItemAdapter adapter = new ItemAdapter(getActivity(), todos, true, true, this);
        rv.setAdapter(adapter);
 
    }
 
    @Override
    public void onDestroy() {
        super.onDestroy();
        realm.close();
    }
 
    @Override
    public void onItemClick(View caller, Item task) {
        ((MainActivity)getActivity()).hideFab();
        EditFragment editFragment = EditFragment.Companion.newInstance(task.getId());
        getActivity().getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.content_main, editFragment, editFragment.getClass().getSimpleName())
                .addToBackStack(editFragment.getClass().getSimpleName())
                .commit();
    }
}

Kemudian kita buat file Kotlin dengan nama EditFragment. class ini merupakan logic untuk mengubah beberapa variabel. Misalnya, ketika akan menambahkan item maka button akan bernama simpan. Tapi, jika item sudah tersimpan dan kita klik maka button akan berubah menjadi ubah. Pada class ini juga Anko digunakan pada bagian method :

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    return UI {
        verticalLayout {
            padding = dip(30)
            var title = editText {
                id = R.id.crud_title
                hintResource = R.string.title_hint
            }
 
            var desc = editText {
                id = R.id.crud_desc
                hintResource = R.string.description_hint
            }
            button {
                id = R.id.crud_add
                textResource = R.string.add_item
                onClick { view -> createItemFrom(title, desc) }
            }
        }
    }.view
}

Pada kode diatas, kita membuat LinearLayout dengan dua buah form input menggunakan editText dan satu Button. Kemudian pada method override fun onActivityCreated(savedInstanceState: Bundle?), ketika item diklik maka akan mencari data berdasarkan id sebagai primary key dan button simpan akan berubah menjadi button ubah 

override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
 
        if(arguments != null && arguments.containsKey(Item_ID_KEY)) {
            val ItemId = arguments.getString(Item_ID_KEY)
            item = realm.where(Item::class.java).equalTo("id", ItemId).findFirst()
            val todoTitle = find<EditText>(R.id.crud_title)
            todoTitle.setText(item?.title)
            val todoDesc = find<EditText>(R.id.crud_desc)
            todoDesc.setText(item?.description)
            val add = find<Button>(R.id.crud_add)
            add.setText(R.string.save)
        }
    }

Kode lengkap dari EditFragment sebagai berikut :

EditFragment.kt
package com.dekikurnia.belajarkotlin
 
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import com.dekikurnia.belajarkotlin.models.Item
import io.realm.Realm
import org.jetbrains.anko.*
import org.jetbrains.anko.support.v4.UI
import org.jetbrains.anko.support.v4.find
import java.util.*
 
class EditFragment : Fragment() {
 
    val Item_ID_KEY: String = "item_id_key"
    val realm: Realm = Realm.getDefaultInstance()
    var item: Item? = null
 
    companion object {
        fun newInstance(id: String): EditFragment {
            var args: Bundle = Bundle()
            args.putString("item_id_key", id)
            var editFragment: EditFragment = newInstance()
            editFragment.arguments = args
            return editFragment
        }
 
        fun newInstance(): EditFragment {
            return EditFragment()
        }
    }
 
    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return UI {
            verticalLayout {
                padding = dip(30)
                var title = editText {
                    id = R.id.crud_title
                    hintResource = R.string.title_hint
                }
 
                var desc = editText {
                    id = R.id.crud_desc
                    hintResource = R.string.description_hint
                }
                button {
                    id = R.id.crud_add
                    textResource = R.string.add_item
                    onClick { view -> createItemFrom(title, desc) }
                }
            }
        }.view
    }
 
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
 
        if(arguments != null && arguments.containsKey(Item_ID_KEY)) {
            val ItemId = arguments.getString(Item_ID_KEY)
            item = realm.where(Item::class.java).equalTo("id", ItemId).findFirst()
            val itemTitle = find<EditText>(R.id.crud_title)
            itemTitle.setText(item?.title)
            val itemDesc = find<EditText>(R.id.crud_desc)
            itemDesc.setText(item?.description)
            val add = find<Button>(R.id.crud_add)
            add.setText(R.string.save)
        }
    }
 
    override fun onDestroy() {
        super.onDestroy()
        realm.close()
    }
   
    private fun createItemFrom(title: EditText, desc: EditText) {
        realm.beginTransaction()
        var t = item?: realm.createObject(Item::class.java)
        t.id = item?.id?: UUID.randomUUID().toString()
        t.title = title.text.toString()
        t.description = desc.text.toString()
        realm.commitTransaction()
        activity.supportFragmentManager.popBackStack();
    }
}

Selesai membuat kode untuk EditFragment, mari kita ubah MainActivity. Pada bagian kode ini logicnya adalah saat FloatingActionButton diklik maka akan memanggil ItemFragment untuk menambah item dan saat memanggil ItemFragment otomatis FloatingActionButton akan menghilang pada bagian method hideFab().Berikut kode lengkapnya :

MainActivity.java
package com.dekikurnia.belajarkotlin;
 
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
 
public class MainActivity extends AppCompatActivity {
    FloatingActionButton fab;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                EditFragment editFragment = EditFragment.Companion.newInstance();
                getSupportFragmentManager()
                        .beginTransaction()
                        .replace(R.id.content_main, editFragment, editFragment.getClass().getSimpleName())
                        .addToBackStack(editFragment.getClass().getSimpleName())
                        .commit();
                hideFab();
            }
        });
 
        ItemFragment fragment = ItemFragment.newInstance();
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.content_main, fragment, fragment.getClass().getSimpleName())
                .commit();
 
        getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
            @Override
            public void onBackStackChanged() {
                int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
                if(backStackCount == 0) {
                    fab.setVisibility(View.VISIBLE);
                }
            }
        });
 
    }
 
    public void hideFab() {
        fab.setVisibility(View.GONE);
    }
}

Kemudian buat class baru dengan nama KotlinMix. berikut kodenya :

package com.dekikurnia.belajarkotlin;
 
import android.app.Application;
import io.realm.Realm;
import io.realm.RealmConfiguration;
 
public class KotlinMix extends Application {
 
    @Override
    public void onCreate() {
        super.onCreate();
 
        RealmConfiguration config = new RealmConfiguration.Builder(this)
                .name("kotlinmix.realm")
                .build();
 
        Realm.setDefaultConfiguration(config);
 
        Realm.deleteRealm(config);
    }
}

Terakhir, rubah AndroidManifest.xml menjadi seperti ini :

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.dekikurnia.belajarkotlin"
   xmlns:android="http://schemas.android.com/apk/res/android">
 
    <application
       android:name=".KotlinMix"
       android:allowBackup="true"
       android:icon="@mipmap/ic_launcher"
       android:label="@string/app_name"
       android:supportsRtl="true"
       android:theme="@style/AppTheme">
        <activity
           android:name=".MainActivity"
           android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
 
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
 
</manifest>

Kode untuk logic aplikasi sudah selesai, silahkan run aplikasi. Mudah-mudahan tidak ada yang error :D, bagi yang kesulitan silahkan tinggalkan di kolom komentar

Post Author: dekikurnia