news

Minggu, 14 Juni 2020

Perkenalan Components Dasar untuk Membuat Aplikasi Android


Dalam modul ini kita akan belajar tentang komponen-komponen dasar yang digunakan untuk membuat aplikasi android yang sederhana. Beberapa komponen di antaranya adalah :

  1. Activity
    Merupakan satu komponen yang berhubungan dengan pengguna. Activity menangani window (tampilan) mana yang akan di tampilkan ke dalam interface (antarmuka). Activity memiliki daur hidup (life cycle) tersendiri yang dimulai dari onCreate hingga onDestroy.
    20170703073131aeda7a107124e97dffabaf3361a6fbdb.png
  2. Intent
    Komunikasi antar komponen di dalam sebuah aplikasi merupakan hal yang sangat sering dilakukan. Inilah peran dari suatu intent. Beberapa fungsi dari intent adalah dapat digunakan untuk menjalankan sebuah activity, mengirimkan pesan ke broadcast receiver, dan dapat juga digunakan untuk berkomunikasi dengan service yang sedang berjalan.
  3. Views and ViewGroup
    Pada dasarnya semua elemen antar pengguna di aplikasi Android dibangun menggunakan dua buah komponen inti, yaitu view dan viewgroup. Sebuah view adalah obyek yang menggambar komponen tampilan ke layar yang mana pengguna dapat melihat dan berinteraksi langsung.
    Contoh komponen turunan dari view seperti :
    • TextView, komponen yang berguna untuk menampilkan teks ke layar.
    • Button, komponen yang membuat pengguna dapat berinteraksi dengan cara ditekan untuk melakukan sesuatu.
    • ImageView, Komponen untuk menampilkan gambar.
    • ListView, komponen untuk menampilkan informasi dalam bentuk list.
    • GridView, komponen untuk menampilkan informasi dalam bentuk grid.
    • RadioButton, komponen yang memungkinkan pengguna dapat memilih satu pilihan dari berbagai pilihan yang disediakan.
    • Checkbox, komponen yang memungkinkan pengguna dapat memilih lebih dari satu dari pilihan yang ada.
  4. Style and Theme
    Prinsip dasar dalam merancang antarmuka aplikasi Android harus mematuhi kaidah yang ditetapkan oleh Design Guideline. Guideline ini dibuat oleh tim Android di Google. Beberapa prinsipnya adalah:
    • Menampilkan informasi yang hanya dibutuhkan.
    • Jika aplikasi meminta izin pengguna untuk melakukan sebuah aksi, maka pengembang harus menyediakan mekanisme untuk membatalkan izin tersebut.
    • Lakukan interupsi jika diperlukan.
    • Menggunakan teks secara singkat. Gunakan gambar untuk menjelaskan informasi secara lebih deskriptif.
    • Jaga data pengguna.
    • Permudah pengguna untuk melakukan sesuatu yang penting secara cepat.
    • Jika terlihat sama, maka perilaku haruslah sama.
    • Bantu pengguna untuk membuat keputusan tapi tetap biarkan pengguna menentukan keputusannya.
  5. RecyclerView
    RecyclerView adalah sebuah komponen tampilan (widget) yang lebih canggih ketimbang pendahulunya listview. Ia bersifat lebih fleksibel. RecyclerView memiliki kemampuan untuk menampilkan data secara efisien dalam jumlah yang besar. Terlebih jika Anda memiliki koleksi data dengan elemen yang mampu berubah-ubah sewaktu dijalankan (runtime).
    201706051440121b186ca7c9c9817ed4f1d51f4e31b09c.png
    Gambar di atas menerangkan beberapa komponen yang harus Anda ketahui sebelum menggunakan recyclerview.
    • RecyclerView dan LayoutManager: Komponen antarmuka yang bertugas untuk menampilkan data set yang dimiliki di dalamnya. Layoutmanager akan mengatur posisi tampilan data baik itu secara list (vertikal), grid (baris dan kolom) atau staggered grid (grid yang memiliki susunan tak seragam / tak beraturan)
    • Adapter: Komponen yang akan mengatur bagaimana menampilkan data set ke dalam RecyclerView. Di sinilah terjadi proses pengisian tampilan (ViewInflate) dari file layout xml untuk tiap elemen dari data yang sebelumnya terpasang (bind) ke dalam RecyclerView.
    • Dataset: Kumpulan data yang dimiliki dan ingin ditampilkan. Bisa berupa array, list maupun obyek map.
    • Item Animator: Ini yang spesial. Kita bisa pasang animasi untuk tiap item di dalamnya. Contoh animasi yang umum seperti penambahan (add) dan penghapusan (removal) item. Kita akan mempelajari hal ini pada materi terpisah

Teori

  1. Activity merupakan sebuah komponen di Android yang berfungsi untuk menampilkan user interface ke layar handset Android pengguna. Ini seperti pada saat Anda melihat daftar percakapan pada aplikasi chat atau daftar email pada aplikasi Gmail di ponsel Android Anda.
  2. Umumnya dalam sebuah aplikasi terdapat lebih dari satu activity yang saling terhubung dengan tugas yang berbeda-beda.
  3. Activity merupakan salah satu komponen penting Android yang memiliki daur hidup (life cycle) dalam sebuah stack pada virtual sandbox yang disiapkan oleh Dalvik Virtual Machine (DVM) atau Android Runtime (ART) yang bersifat last in first out.
  4. Pada implementasinya, activity selalu memiliki satu layout user interface dalam bentuk berkas xml.
  5. Suatu aplikasi Android bisa memiliki lebih dari satu activity dan harus terdaftar di berkas AndroidManifest.xml sebagai sub aplikasi.
  6. Sebuah class Java dinyatakan sebuah activity jika mewarisi (extends) superclass Activity atau turunannya seperti AppCompatActivity dan FragmentActivity.

Untuk lebih mendalami activity, kami menyarankan Anda untuk membaca referensi berikut :

Activity Lifecycle

201609211453443ec948a46aa87264bbf9fb0e3c
Developer yang baik harus mengetahui secara detail tentang life cycle sebuah activity. Terutama untuk melakukan aksi yang tepat, saat terjadi perubahan state activity. Callback methods yang ada dapat digunakan untuk melakukan beragam proses terkait state dari activity. Misalnya melakukan semua inisialisasi komponen di onCreate(), melakukan disconnect terhadap koneksi ke server pada onStop() atau onDestroy() dan lain sebagainya.
Pemahaman yang baik tentang daur hidup activity akan membuat implementasi rancangan aplikasi Anda menjadi lebih baik. Hal ini juga akan meminimalisir terjadinya error/bug/force close yang tidak diinginkan.

Last In, First Out (LIFO)

20170515054021b0fdcc4af411dd804660ac803ea3ae2c.PNG

Gambar 1
Gambar 2
Gambar 3
Aktif: Activity 1
onCreate() → onStart() → onResume()
Aktif: Activity 2
Stack append: Activity 2 [ onResume() ]
Activity 1
onStop() → onRestart() → onStart() → onResume()
Aksi: Klik Button1 (Pindah)
Aksi: Klik Hardware Back Button
Aktif: Activity 1
Stack append: Activity 1 [ onStop() ]
Activity 2 [ finish() ]
Stack pop: Activity 2 [ onDestroy() ]

  1. Gambar 1
    Jika Anda memiliki sebuah aplikasi yang terdiri dari 2 activity, maka activity pertama akan dijalankan setelah pengguna meluncurkan aplikasi melalui ikon aplikasi di layar device. Activity yang ada saat ini berada pada posisi activity running setelah melalui beberapa state onCreate (created) → onStart (started) → onResume (resumed) dan masuk ke dalam sebuah stack activity.
    Bila pada activity pertama Anda menekan sebuah tombol untuk menjalankan activity kedua, maka posisi state dari activity pertama berada pada posisi stop. Saat itu, callback onStop() pada activity pertama akan dipanggil.
    Ini terjadi karena activity pertama sudah tidak berada pada layar foreground / tidak lagi ditampilkan. Semua informasi terakhir pada activity pertama akan disimpan secara otomatis.
    Sementara itu, activity kedua masuk ke dalam stack dan menjadi activity terakhir yang masuk.
  2. Gambar 2
    Activity kedua sudah muncul di layar sekarang. Ketika Anda menekan tombol back pada physical button menu utama atau menjalankan metode finish(), maka activity kedua Anda akan dikeluarkan dari stack.
    Pada kondisi di atas, state activity kedua akan berada pada destroy. Oleh karenanya, metode onDestroy() akan dipanggil.
    Kejadian keluar dan masuk stack pada proses di atas menandakan sebuah model Last In, First Out. Activity kedua menjadi yang terakhir masuk stack (Last In) dan yang paling pertama keluar dari stack (First Out).
  3. Gambar 3Activity pertama akan dimunculkan kembali di layar setelah melalui beberapa state dengan rangkaian callback method yang terpanggil, onStop → onRestart → onStart → onResume.

Detailnya dapat Anda baca di sini :

Saving Activity State

Ketika sebuah activity mengalami pause kemudian resume, maka state dari sebuah activity tersebut dapat terjaga. Sebabnya, obyek activity masih tersimpan di memory sehingga dapat dikembalikan state-nya.
Dengan menjaga state dari activity, maka ketika activity tersebut ditampilkan, kondisinya akan tetap sama dengan kondisi sebelumnya.
Akan tetapi ketika sistem menghancurkan activity untuk keperluan memori misalnya karena memori habis, maka obyek activity dihancurkan. Alhasil, ketika activity ingin ditampilkan kembali diperlukan proses recreate activity yang dihancurkan tadi.
Kejadian di atas adalah hal yang lumrah terjadi. Oleh karena itu, perubahan yang terjadi pada activity perlu disimpan terlebih dahulu sebelum ia dihancurkan. Di sinilah metode onSaveInstanceState() digunakan.
Dalam onSaveInstanceState terdapat bundle yang dapat digunakan untuk menyimpan informasi. Informasi dapat disimpan dengan memanfaatkan fungsi seperti putString() dan putInt().
Ketika activity di-restart, bundle akan diberikan kepada metode onCreate dan onRestoreInstanceState. Bundle tersebut akan dimanfaatkan untuk mengembalikan kembali perubahan yang telah terjadi sebelumnya.
20161102140031b539b0f6990d374fe601740a2173b41e.png
Proses penghancuran activity dapat juga terjadi ketika terdapat perubahan konfigurasi seperti perubahan orientasi layar (portrait-landscape), keyboard availability, dan perubahan bahasa. Penghancuran ini akan menjalankan callback method onDestroy dan kemudian menjalankan onCreate. Penghancuran ini dimaksudkan agar activity dapat menyesuaikan diri dengan konfigurasi baru yang muncul pada kejadian-kejadian sebelumnya.
Hal yang perlu diingat ketika menggunakan onSaveInstanceState adalah untuk tidak menyimpan data yang besar pada bundle. Contohnya, hindari penyimpanan data bitmap pada bundle. Bila data pada bundle berukuran besar, proses serialisasi dan deserialisasi akan memakan banyak memori. 
Contoh Project Sederhana
Codelab ini bertujuan untuk mengimplementasikan komponen activity pada aplikasi pertama yang Anda bangun. Harapannya aktifitas ini dapat memberi gambaran yang jelas tentang cara kerja activity.
Codelab pertama adalah dengan membuat aplikasi yang dapat menghitung volume balok. Seperti ini tampilannya.201811121622411d5143763cc8715c535d1327e772d305

Logika Dasar

Melakukan input ke dalam obyek EditText → melakukan validasi input → melakukan perhitungan volume balok ketika tombol hitung diklik.

Codelab Membuat Proyek Baru

  1. Buat proyek baru dengan klik File → New → New Project pada Android Studio Anda atau Anda bisa memilih Start a new Android Studio project di bagian dashboard.2018111209000871ac40d0c865aa819a08c988ddde4b4d
  2. Pada bagian ini kita akan memilih tipe activity awal dari template yang telah disediakan. Saat ini Android Studio sudah menyediakan berbagai macam template activity dari yang paling sederhana hingga yang paling kompleks seperti:
    Add No Activity                           : Tidak ada activity yang ditambahkan
    Basic Activity : Activity dengan template komponen material design seperti FloatingActionButton
    Bottom Navigation Activity  : Activity dengan tampilan side bar menu di bagian bawah
    Empty Activity     : Activity dalam bentuk yang paling dasar
    Fragment + ViewModel              : Activity dengan menerapkan architecture component
    Fullscreen Activity                       : Activity fullscreen tanpa status bar
    Google AdMob Ads Activity       : Activity dengan konfigurasi default iklan Admob
    Google Maps Activity : Activity dengan menyediakan konfigurasi dasar Google Maps
    Login Activity : Activity untuk halaman login
    Master / Detail Flow                  : Activity yang diperuntukan untuk alur aplikasi master detail pada peranti tablet
    Navigation Drawer Activity : Activity dengan tampilan side bar menu
    Scrolling Activity : Activity dengan kemampuan scroll konten didalamnya secara vertikal
    Settings Activity : Activity yang diperuntukkan untuk konfigurasi aplikasi
    Tabbed Activity                           : Activity yang diperuntukkan untuk menampilkan lebih dari satu tampilan, dapat digeser ke kanan dan ke kiri (swipe) dan dengan menggunakan komponen ViewPager

    Selain itu, Anda juga bisa memilih target device mana yang akan dibuat seperti Phone and TabletWear OSTVAndroid Auto atau Android Things.
    2019011614581831311ab983af02c0dc716ffb6a567043Saat ini kita pilih tipe Empty Activity, klik Next untuk melanjutkan.
  3. Selanjutnya masukkan nama aplikasi dan nama package aplikasi Anda. Sebaiknya jangan sama dengan apa yang ada di contoh, karena ini berfungsi sebagai id dari aplikasi yang Anda buat. Kemudian Anda bisa menentukan lokasi proyek yang akan Anda buat. Setelah itu pilih tipe gawai/peranti (device) untuk aplikasi beserta target minimum SDK yang akan digunakan. Pilihan target Android SDK akan mempengaruhi banyaknya peranti yang dapat menggunakan aplikasi. Di sini kita memilih nilai minimum SDK kita pasang ke Level 21 (Lollipop). Klik Finish untuk melanjutkan.
    20190826101441e4f07a473ed06b879e730c492ad26925
    Catatan: Untuk Android Studio versi 3.4.1 ke bawah, penggunaan AndroidX belum menjadi default. Jadi, silakan beri tanda centang pada "Use AndroidX artifacts" di setiap kali membuat project. Informasi lebih detail mengenai AndroidX bisa Anda lihat di sini, dan untuk melihat perubahan antara sebelum dan sesudah AndroidX, atau cara migrasi menggunakan AndroidX bisa lihat di sini. Perlu Anda ketahui juga, ketika Anda sudah menggunakan AndroidX maka Anda tidak bisa menambahkan library lama atau sebelum AndroidX.

    Kelas ini sudah mendukung bahasa Kotlin. Untuk menggunakan bahasa Kotlin ubahlah languages dari Java menjadi Kotlin, maka secara otomatis Android Studio akan menyesuaikan dengan bahasa Kotlin.
  4. Tampilan layar Anda akan seperti contoh di bawah ini:
    20190116151359393af0e1733c0c2b819b50a2e1d5d471
  5. Di sebelah kanan Anda adalah workspace di mana Activity Anda berada dan bernama MainActivity dengan layout-nya activity_main.xml. Di sebelah kiri Anda terdapat struktur proyek, di mana nanti kita akan banyak menambahkan berbagai komponen baru, asset dan library. Untuk lebih mengenal Android Studio lebih dalam silakan baca materi ini https://developer.android.com/studio/intro/index.html.

Selanjutnya kita akan mulai melakukan pengkodean aplikasi atau lebih enaknya disebut ngoding.
Berikut flow umumnya:
  1. Ngoding Layout untuk user interface aplikasi.
  2. Ngoding Activity untuk menambahkan logika aplikasi.
Untuk mengoptimalkan proses pengetikan, Anda dapat memanfaatkan code completion dengan menekan ctrl + space. Android Studio juga akan mengimpor package dari komponen yang digunakan. 
Dilarang Keras untuk copy - paste! Ngoding pelan-pelan akan membuat Anda lebih jago di masa depan.
Selamat ngoding!

Codelab Layouting

Menambahkan Code Sederhana pada Layout Activity

  1. Silakan pilih tab berkas activity_main.xml pada workspace Anda(res/layout/activity_main.xml).
    201901161518426978d7756dd739230c63bb08f97581e6Pastikan project window pada pilihan Android, seperti di bawah ini.
    20190116151903ed13f27a41c64cb3b1abfc270f21e22cMaka akan ada tampilan seperti ini, kemudian pilih tab Code di sebelah pojok kanan atas.
    20200504155040c3dba1236b44fc8e13e48c9c5980717e.pngDan tambahkan baris-baris berikut:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:tools="http://schemas.android.com/tools"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="match_parent"
  6.     android:padding="16dp"
  7.     android:orientation="vertical">
  8.  
  9.     <TextView
  10.         android:layout_width="match_parent"
  11.         android:layout_height="wrap_content"
  12.         android:text="Panjang" />
  13.     <EditText
  14.         android:id="@+id/edt_length"
  15.         android:layout_width="match_parent"
  16.         android:layout_height="wrap_content"
  17.         android:inputType="numberDecimal"
  18.         android:lines="1" />
  19.     <TextView
  20.         android:layout_width="match_parent"
  21.         android:layout_height="wrap_content"
  22.         android:text="Lebar" />
  23.     <EditText
  24.         android:id="@+id/edt_width"
  25.         android:layout_width="match_parent"
  26.         android:layout_height="wrap_content"
  27.         android:inputType="numberDecimal"
  28.         android:lines="1" />
  29.     <TextView
  30.         android:layout_width="match_parent"
  31.         android:layout_height="wrap_content"
  32.         android:text="Tinggi" />
  33.     <EditText
  34.         android:id="@+id/edt_height"
  35.         android:layout_width="match_parent"
  36.         android:layout_height="wrap_content"
  37.         android:inputType="numberDecimal"
  38.         android:lines="1" />
  39.     <Button
  40.         android:id="@+id/btn_calculate"
  41.         android:layout_width="match_parent"
  42.         android:layout_height="wrap_content"
  43.         android:text="Hitung" />
  44.     <TextView
  45.         android:id="@+id/tv_result"
  46.         android:layout_width="match_parent"
  47.         android:layout_height="wrap_content"
  48.         android:gravity="center"
  49.         android:text="Hasil"
  50.         android:textSize="24sp"
  51.         android:textStyle="bold" />
  52. </LinearLayout>

  1. Perlu diperhatikan root layout (tag layout terluar) yang dipakai di sini adalah LinearLayout. Jika kita menggunakan Android Studio versi 3 maka secara default root yang dipakai adalah ConstraintLayout. Agar sesuai dengan latihan ini, kita tinggal menggantinya menjadi LinearLayout.
    Untuk Layout akan dibahas nanti pada modul yang berbeda.
  2. Kemudian akan muncul warning pada atribut android:text pada layout tersebut.
    20181112092821af9c83a6062f6880c683b41a9e6d2fd1Ini karena kita melakukan hardcoding pada nilai string-nya. Mari kita hilangkan code warning tersebut dengan menekan Alt+Enter (option + return pada Mac) atau menekan lampu kuning yang muncul pada attribut android:text.
    Akan muncul dialog seperti ini, pilih extract string resource.
    201811120923086c6e448fde7b10eeac1a7ef4fbf25924
  3. Kemudian akan muncul dialog seperti di bawah ini. Sesuaikan dengan nama yang ada.
    201811120927217800750fc9fc17abef37ef35bb3ccb31
  4. Fungsi extract string resource akan secara otomatis menambahkan nilai dari android:text ke dalam berkas res → values → strings.xml.
    2018111209261415bb8ae12764e29af67533cb284e42ccLakukan hal yang sama pada View lainnya hingga tidak ada warning lagi. Jika kita buka berkas strings.xml, maka isinya akan menjadi seperti ini:


    1. <resources>

    2.     <string name="app_name">BarVolume</string>

    3.     <string name="width">Lebar</string>

    4.     <string name="height">Tinggi</string>

    5.     <string name="calculate">Hitung</string>

    6.     <string name="result">Hasil</string>

    7.     <string name="length">Panjang</string>

    8. </resources>


  5. Maka kode di dalam activity_main.xml akan menjadi seperti ini:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:tools="http://schemas.android.com/tools"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="match_parent"
  6.     android:padding="16dp"
  7.     android:orientation="vertical">
  8.  
  9.     <TextView
  10.         android:layout_width="match_parent"
  11.         android:layout_height="wrap_content"
  12.         android:text="@string/length" />
  13.  
  14.     <EditText
  15.         android:id="@+id/edt_length"
  16.         android:layout_width="match_parent"
  17.         android:layout_height="wrap_content"
  18.         android:inputType="numberDecimal"
  19.         android:lines="1" />
  20.  
  21.     <TextView
  22.         android:layout_width="match_parent"
  23.         android:layout_height="wrap_content"
  24.         android:text="@string/width" />
  25.  
  26.     <EditText
  27.         android:id="@+id/edt_width"
  28.         android:layout_width="match_parent"
  29.         android:layout_height="wrap_content"
  30.         android:inputType="numberDecimal"
  31.         android:lines="1" />
  32.  
  33.     <TextView
  34.         android:layout_width="match_parent"
  35.         android:layout_height="wrap_content"
  36.         android:text="@string/height" />
  37.  
  38.     <EditText
  39.         android:id="@+id/edt_height"
  40.         android:layout_width="match_parent"
  41.         android:layout_height="wrap_content"
  42.         android:inputType="numberDecimal"
  43.         android:lines="1" />
  44.  
  45.     <Button
  46.         android:id="@+id/btn_calculate"
  47.         android:layout_width="match_parent"
  48.         android:layout_height="wrap_content"
  49.         android:text="@string/calculate" />
  50.  
  51.     <TextView
  52.         android:id="@+id/tv_result"
  53.         android:layout_width="match_parent"
  54.         android:layout_height="wrap_content"
  55.         android:gravity="center"
  56.         android:text="@string/result"
  57.         android:textSize="24sp"
  58.         android:textStyle="bold" />
  59. </LinearLayout>





  1. Jika Anda perhatikan, hasil layout sementara akan menjadi seperti ini:
    201901161526273401ae29ed3356f270242d25a26182cc

Codelab Kode Logika

Menambahkan Kode Logika Sederhana pada MainActivity.

  1. Selanjutnya setelah selesai, lanjutkan dengan membuka berkas MainActivity dan lanjutkan ngoding baris-baris di bawah ini.
  2. Tambahkan beberapa variabel yang akan digunakan untuk menampung View.


  1. private EditText edtWidth;

  2. private EditText edtHeight;

  3. private EditText edtLength;

  4. private Button btnCalculate;

  5. private TextView tvResult;







  1. private lateinit var edtWidth: EditText

  2. private lateinit var edtHeight: EditText

  3. private lateinit var edtLength: EditText

  4. private lateinit var btnCalculate: Button

  5. private lateinit var tvResult: TextView




Kemudian inisiasi variabel yang telah kita buat dengan menambahkan kode berikut di dalam metode onCreate.





  1. @Override

  2. protected void onCreate(Bundle savedInstanceState) {

  3.     super.onCreate(savedInstanceState);

  4.     setContentView(R.layout.activity_main);

  5.  

  6.     edtWidth = findViewById(R.id.edt_width);

  7.     edtHeight = findViewById(R.id.edt_height);

  8.     edtLength = findViewById(R.id.edt_length);

  9.     btnCalculate = findViewById(R.id.btn_calculate);

  10.     tvResult = findViewById(R.id.tv_result);

  11. }








  1. override fun onCreate(savedInstanceState: Bundle?) {

  2.     super.onCreate(savedInstanceState)

  3.     setContentView(R.layout.activity_main)

  4.  

  5.     edtWidth = findViewById(R.id.edt_width)

  6.     edtHeight = findViewById(R.id.edt_height)

  7.     edtLength = findViewById(R.id.edt_length)

  8.     btnCalculate = findViewById(R.id.btn_calculate)

  9.     tvResult = findViewById(R.id.tv_result)

  10. }




Kemudian tambahkan implementasi interface onClickListener pada kelas MainActivity.






  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener {

  2.  

  3.     ...

  4.  

  5. }










  1. class MainActivity : AppCompatActivity(), View.OnClickListener {

  2.  

  3.     ...

  4.  

  5. }



Jika terdapat baris merah seperti ini:
2018111209435526d64916135ea2bf20359909c26e7840
Jangan khawatir! Silakan klik di atas baris merah tersebut dan klik pada ikon bola lampuAtau dengan tekan tombol Alt+Enter (option+return pada Mac) atau menekan lampu merah yang muncul lalu pilih implement methods.
20181112094504444454ccef1a16a24553dd73e0ea2ecc






  1. @Override

  2. protected void onCreate(Bundle savedInstanceState) {

  3.     super.onCreate(savedInstanceState);

  4.     setContentView(R.layout.activity_main);

  5.    

  6.     ...

  7.     

  8.     btnCalculate.setOnClickListener(this);

  9. }

  10.  

  11. @Override

  12. public void onClick(View v) {

  13.     if (v.getId() == R.id.btn_calculate) {

  14.         String inputLength = edtLength.getText().toString().trim();

  15.         String inputWidth = edtWidth.getText().toString().trim();

  16.         String inputHeight = edtHeight.getText().toString().trim();


  17.         boolean isEmptyFields = false;

  18.         boolean isInvalidDouble = false;


  19.         if (TextUtils.isEmpty(inputLength)) {

  20.             isEmptyFields = true;

  21.             edtLength.setError("Field ini tidak boleh kosong");

  22.         }


  23.         if (TextUtils.isEmpty(inputWidth)) {

  24.             isEmptyFields = true;

  25.             edtWidth.setError("Field ini tidak boleh kosong");

  26.         }


  27.         if (TextUtils.isEmpty(inputHeight)) {

  28.             isEmptyFields = true;

  29.             edtHeight.setError("Field ini tidak boleh kosong");

  30.         }


  31.         Double length = toDouble(inputLength);

  32.         Double width = toDouble(inputWidth);

  33.         Double height = toDouble(inputHeight);


  34.         if (length == null) {

  35.             isInvalidDouble = true;

  36.             edtLength.setError("Field ini harus berupa nomer yang valid");

  37.         }


  38.         if (width == null) {

  39.             isInvalidDouble = true;

  40.             edtWidth.setError("Field ini harus berupa nomer yang valid");

  41.         }


  42.         if (height == null) {

  43.             isInvalidDouble = true;

  44.             edtHeight.setError("Field ini harus berupa nomer yang valid");

  45.         }


  46.         if (!isEmptyFields && !isInvalidDouble) {


  47.             double volume = length * width * height;


  48.             tvResult.setText(String.valueOf(volume));

  49.         }

  50.     }

  51. }

















  1. override fun onCreate(savedInstanceState: Bundle?) {

  2.     super.onCreate(savedInstanceState)

  3.     setContentView(R.layout.activity_main)

  4.  

  5.     ...

  6.  

  7.     btnCalculate.setOnClickListener(this)

  8. }

  9.  

  10. override fun onClick(v: View) {

  11.     if (v.id == R.id.btn_calculate) {

  12.         val inputLength = edtLength.text.toString().trim()

  13.         val inputWidth = edtWidth.text.toString().trim()

  14.         val inputHeight = edtHeight.text.toString().trim()


  15.         var isEmptyFields = false

  16.         var isInvalidDouble = false


  17.         if (inputLength.isEmpty()) {

  18.             isEmptyFields = true

  19.             edtLength.error = "Field ini tidak boleh kosong"

  20.         }


  21.         if (inputWidth.isEmpty()) {

  22.             isEmptyFields = true

  23.             edtWidth.error = "Field ini tidak boleh kosong"

  24.         }


  25.         if (inputHeight.isEmpty()) {

  26.             isEmptyFields = true

  27.             edtHeight.error = "Field ini tidak boleh kosong"

  28.         }


  29.         val length = toDouble(inputLength)

  30.         val width = toDouble(inputWidth)

  31.         val height = toDouble(inputHeight)


  32.         if (length == null) {

  33.             isInvalidDouble = true

  34.             edtLength.error = "Field ini harus berupa nomer yang valid"

  35.         }


  36.         if (width == null) {

  37.             isInvalidDouble = true

  38.             edtWidth.error = "Field ini harus berupa nomer yang valid"

  39.         }


  40.         if (height == null) {

  41.             isInvalidDouble = true

  42.             edtHeight.error = "Field ini harus berupa nomer yang valid"

  43.         }


  44.         if (!isEmptyFields && !isInvalidDouble) {

  45.             val volume = length as Double * width as Double * height as Double

  46.             tvResult.text = volume.toString()

  47.         }

  48.     }

  49. }






Terakhir tambahkan kode untuk validasi nilai double.














  1. private Double toDouble(String str) {

  2.     try {

  3.         return Double.valueOf(str);

  4.     } catch (NumberFormatException e) {

  5.         return null;

  6.     }

  7. }




  1. private fun toDouble(str: String): Double? {

  2.     return try {

  3.         str.toDouble()

  4.     } catch (e: NumberFormatException) {

  5.         null

  6.     }

  7. }


Akhirnya kelas MainActivity akan memiliki kode seperti berikut ini.


  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener {

  2.     private EditText edtWidth, edtHeight, edtLength;

  3.     private Button btnCalculate;

  4.     private TextView tvResult;

  5.  

  6.     @Override

  7.     protected void onCreate(Bundle savedInstanceState) {

  8.         super.onCreate(savedInstanceState);

  9.         setContentView(R.layout.activity_main);

  10.  

  11.         edtWidth = findViewById(R.id.edt_width);

  12.         edtHeight = findViewById(R.id.edt_height);

  13.         edtLength = findViewById(R.id.edt_length);

  14.         btnCalculate = findViewById(R.id.btn_calculate);

  15.         tvResult = findViewById(R.id.tv_result);

  16.  

  17.         btnCalculate.setOnClickListener(this);

  18.     }

  19.  

  20.     @Override

  21.     public void onClick(View v) {

  22.         if (v.getId() == R.id.btn_calculate) {

  23.             String inputLength = edtLength.getText().toString().trim();

  24.             String inputWidth = edtWidth.getText().toString().trim();

  25.             String inputHeight = edtHeight.getText().toString().trim();

  26.  

  27.             boolean isEmptyFields = false;

  28.             boolean isInvalidDouble = false;

  29.  

  30.             if (TextUtils.isEmpty(inputLength)) {

  31.                 isEmptyFields = true;

  32.                 edtLength.setError("Field ini tidak boleh kosong");

  33.             }

  34.  

  35.             if (TextUtils.isEmpty(inputWidth)) {

  36.                 isEmptyFields = true;

  37.                 edtWidth.setError("Field ini tidak boleh kosong");

  38.             }

  39.  

  40.             if (TextUtils.isEmpty(inputHeight)) {

  41.                 isEmptyFields = true;

  42.                 edtHeight.setError("Field ini tidak boleh kosong");

  43.             }

  44.  

  45.             Double length = toDouble(inputLength);

  46.             Double width = toDouble(inputWidth);

  47.             Double height = toDouble(inputHeight);

  48.  

  49.             if (length == null) {

  50.                 isInvalidDouble = true;

  51.                 edtLength.setError("Field ini harus berupa nomer yang valid");

  52.             }

  53.  

  54.             if (width == null) {

  55.                 isInvalidDouble = true;

  56.                 edtWidth.setError("Field ini harus berupa nomer yang valid");

  57.             }

  58.  

  59.             if (height == null) {

  60.                 isInvalidDouble = true;

  61.                 edtHeight.setError("Field ini harus berupa nomer yang valid");

  62.             }

  63.  

  64.             if (!isEmptyFields && !isInvalidDouble) {

  65.                 double volume = length * width * height;

  66.                 tvResult.setText(String.valueOf(volume));

  67.             }

  68.         }

  69.     }

  70.  

  71.     private Double toDouble(String str) {

  72.         try {

  73.             return Double.valueOf(str);

  74.         } catch (NumberFormatException e) {

  75.             return null;

  76.         }

  77.     }

  78. }




  1. class MainActivity : AppCompatActivity(), View.OnClickListener {

  2.     private lateinit var edtWidth: EditText

  3.     private lateinit var edtHeight: EditText

  4.     private lateinit var edtLength: EditText

  5.     private lateinit var btnCalculate: Button

  6.     private lateinit var tvResult: TextView

  7.  

  8.     override fun onCreate(savedInstanceState: Bundle?) {

  9.         super.onCreate(savedInstanceState)

  10.         setContentView(R.layout.activity_main)

  11.  

  12.         edtWidth = findViewById(R.id.edt_width)

  13.         edtHeight = findViewById(R.id.edt_height)

  14.         edtLength = findViewById(R.id.edt_length)

  15.         btnCalculate = findViewById(R.id.btn_calculate)

  16.         tvResult = findViewById(R.id.tv_result)

  17.  

  18.         btnCalculate.setOnClickListener(this)

  19.     }

  20.  

  21.     override fun onClick(v: View) {

  22.         if (v.id == R.id.btn_calculate) {

  23.             val inputLength = edtLength.text.toString().trim()

  24.             val inputWidth = edtWidth.text.toString().trim()

  25.             val inputHeight = edtHeight.text.toString().trim()


  26.             var isEmptyFields = false

  27.             var isInvalidDouble = false


  28.             if (inputLength.isEmpty()) {

  29.                 isEmptyFields = true

  30.                 edtLength.error = "Field ini tidak boleh kosong"

  31.             }

  32.  

  33.             if (inputWidth.isEmpty()) {

  34.                 isEmptyFields = true

  35.                 edtWidth.error = "Field ini tidak boleh kosong"

  36.             }

  37.  

  38.             if (inputHeight.isEmpty()) {

  39.                 isEmptyFields = true

  40.                 edtHeight.error = "Field ini tidak boleh kosong"

  41.             }


  42.             val length = toDouble(inputLength)

  43.             val width = toDouble(inputWidth)

  44.             val height = toDouble(inputHeight)


  45.             if (length == null) {

  46.                 isInvalidDouble = true

  47.                 edtLength.error = "Field ini harus berupa nomer yang valid"

  48.             }


  49.             if (width == null) {

  50.                 isInvalidDouble = true

  51.                 edtWidth.error = "Field ini harus berupa nomer yang valid"

  52.             }


  53.             if (height == null) {

  54.                 isInvalidDouble = true

  55.                 edtHeight.error = "Field ini harus berupa nomer yang valid"

  56.             }


  57.             if (!isEmptyFields && !isInvalidDouble) {

  58.                 val volume = length as Double * width as Double * height as Double

  59.                 tvResult.text = volume.toString()

  60.             }

  61.         }

  62.     }

  63.  

  64.     private fun toDouble(str: String): Double? {

  65.         return try {

  66.             str.toDouble()

  67.         } catch (e: NumberFormatException) {

  68.             null

  69.         }

  70.     }

  71. }


  1. Setelah selesai, silakan jalankan aplikasi dengan memilih menu Run → Run ‘app’ dari menu bar. 201901170910324f3aff89c4b13f86e6f864536dc9d37aKemudian ada pilihan seperti ini. 201901170917292fa4e95ece51ff9ab1f2b147f881f674Itu tandanya adb (Android Debugger) pada peranti yang Anda punya telah terhubung dengan Android Studio. Jika Anda tidak memiliki peranti, maka Anda dapat menggunakan emulator. Ikuti materinya di modul sebelumnya https://www.dicoding.com/academies/14/tutorials/1132 atau di sini https://developer.android.com/studio/run/managing-avds.html. Kami merekomendasikan Anda menggunakan peranti Android sewaktu mengembangkan aplikasi. Selain karena beban memori pada peranti Anda akan jadi lebih rendah, pendekatan ini juga akan memungkinkan Anda untuk merasakan bagaimana aplikasi berjalan di device sebenarnya. Pilih OK untuk menjalankan dan tunggu hingga proses building dan instalasi APK selesai. Jika sudah, seharusnya hasilnya akan seperti ini. 201811121622041e168e77704b819eb68061c099ef81b2.gifSilakan masukkan nilai panjang, lebar dan tinggi kemudian tekan tombol Hitung dan hasilnya akan ditampilkan di obyek textview tvHasil.
  2. Apakah kita sudah selesai? Belum! Masih ada yang kurang. Ketika nilai volume sudah dihitung dan kemudian terjadi pergantian orientasi (portrait-landscape) pada peranti, maka hasil perhitungan tadi akan hilang. 201811120958228d415ed4f5415b87400b5663e3eabd4bUntuk mengatasinya, tambahkan metode onSaveInstanceState() pada MainActivity dan sesuaikan seperti berikut:


  1. private static final String STATE_RESULT = "state_result";

  2.  

  3. ...

  4.  

  5. @Override

  6. protected void onSaveInstanceState(Bundle outState) {

  7.     super.onSaveInstanceState(outState);

  8.     outState.putString(STATE_RESULT, tvResult.getText().toString());

  9. }




  1. companion object {

  2.     private const val STATE_RESULT = "state_result"

  3. }

  4.  

  5. ...

  6.  

  7. override fun onSaveInstanceState(outState: Bundle) {

  8.     super.onSaveInstanceState(outState)

  9.     outState.putString(STATE_RESULT, tvResult.text.toString())

  10. }


Kemudian tambahkan juga beberapa baris berikut pada baris terakhir metode onCreate.


  1. @Override

  2. protected void onCreate(Bundle savedInstanceState) {

  3.     super.onCreate(savedInstanceState);

  4.     setContentView(R.layout.activity_main);

  5.  

  6.     ...

  7.  

  8.     if (savedInstanceState != null) {

  9.         String result = savedInstanceState.getString(STATE_RESULT);

  10.         tvResult.setText(result);

  11.     }

  12. }




  1. override fun onCreate(savedInstanceState: Bundle?) {

  2.     super.onCreate(savedInstanceState)

  3.     setContentView(R.layout.activity_main)

  4.  

  5.     ...

  6.  

  7.     if (savedInstanceState != null) {

  8.         val result = savedInstanceState.getString(STATE_RESULT) as String

  9.         tvResult.text = result

  10.     }

  11. }


  1. Silakan jalankan kembali aplikasinya. Ulangi proses perhitungan seperti sebelumnya. Kemudian ganti orientasi peranti Anda. Jika sudah benar maka hasil perhitungan tidak akan hilang. 

Bedah Kode

Pembahasan tentang layout xml

Layout merupakan user interface dari suatu activity. Layout dituliskan dalam format xml (extensible markup language).


  1. xml version="1.0" encoding="utf-8"?>


Baris ini mengidentifikasi bahwa berkas ini berformat xml.


  1. xmlns:android="http://schemas.android.com/apk/res/android"


Kode di atas menandakan namespace yang digunakan dalam keseluruhan berkas xml ini.

Macam Views

Di sini kita menggunakan beberapa komponen user interface yang disebut view. Di antaranya:
TextView             : Komponen view untuk menampilkan teks ke layar
EditText               : Komponen view untuk memberikan input teks
Button                  : Komponen view untuk melakukan sebuah aksi klik
LinearLayout     : Komponen view bertipe viewgroup yang menjadi parent dari semua sub komponen view (sub view) di dalamnya. Komponen ini bersifat sebagai kontainer untuk komponen lain dengan orientasi secara vertikal atau horizontal.
Cara membaca :


  1.  <TextView

  2.     android:layout_width="match_parent"

  3.     android:layout_height="wrap_content"

  4.     android:text="@string/calculate"

  5.     android:layout_marginBottom="16dp"/>


Komponen di atas adalah sebuah TextView. Perhatikan gambar di bawah ini. Warna ungu menandakan namespace yang digunakan; warna biru adalah atribut dari komponen dan warna hijau adalah nilai dari atribut. Penjelasannya seperti di bawah ini:
2016110214142154500af4d8d662f855314a704a
20161102141427e71b0d44f5baef3f1395940442
match_parentIni berarti bahwa ukuran dimensi sebuah View disesuaikan dengan ukuran layar secara horizontal jika pada layout_width dan vertikal jika pada layout_height.
wrap_content : Ini berarti bahwa ukuran dimensi sebuah View disesuaikan dengan ukuran konten di dalamnya baik secara horizontal pada layout_width dan vertikal jika pada layout_height.
@string/calculate: value calculate berasal dari berkas strings.xml yang bisa Anda lihat dengan cara menekan dan tahan tombol Ctrl (atau command) + arahkan kursor ke atasnya dan kemudian klik sekali. .
20180806171303692bcbb8c9bac3045c0da7b981d59067.
Penggunaan centralize resource value akan memudahkan Anda sewaktu mengembangkan aplikasi Android. Cara tersebut digunakan agar Anda tidak menulis nilai yang sama berulang-ulang. 

Apa itu ‘@+id/’ ? 

Salah satu contoh penerapan penggunaan @+id/ sebagai berikut:


  1. <Button

  2.     android:id="@+id/btn_calculate"

  3.     android:layout_width="match_parent"

  4.     android:layout_height="wrap_content"

  5.     android:text="@string/calculate"/>


Penjelasannya sebagai berikut:


  1. android:id="@+id/btn_calculate"


Jika kita memberikan id pada sebuah view maka kita telah memberikan identifier untuk view tersebut. Pemberian id ini dimaksudkan agar kita bisa melakukan manipulasi/pengendalian pada level logic di komponen seperti activity atau fragment.
Id di atas akan diciptakan di berkas R dan disimpan dalam bentuk hexa bertipe data integer public static final int btn_calculate=0x7f0b0057.
2016110214161078fb3d968af6fd3f8cfc0dbfe0
Acuan untuk menyusun tampilan pada relativelayout akan dibahas pada modul selanjutnya.

Pembahasan tentang Logika Kode

Kode logika dituliskan ke dalam kelas Java atau Koltin. Di sinilah semua aktifitas dari suatu aplikasi berjalan.
Activity


  1. public class MainActivity extends AppCompatActivity 




  1. class MainActivity : AppCompatActivity()



Menandakan bahwa kelas Java / Kotlin di atas merupakan sebuah activity karena inherit ke superclass bernama AppCompatActivity.
OnClickListener


  1. implements View.OnClickListener




  1. , View.OnClickListener 


Ini adalah listener yang kita implementasikan untuk memantau kejadian klik pada komponen tombol (button).
Views


  1. private EditText edtWidth;

  2. private EditText edtHeight;

  3. private EditText edtLength;

  4. private Button btnCalculate;

  5. private TextView tvResult;




  1. private lateinit var edtWidth: EditText

  2. private lateinit var edtHeight: EditText

  3. private lateinit var edtLength: EditText

  4. private lateinit var btnCalculate: Button

  5. private lateinit var tvResult: TextView


Kode di atas mendeklarasikan semua komponen view yang akan dimanipulasi. Kita deklarasikan secara global agar bisa dikenal di keseluruhan bagian kelas.
OnCreate


  1. @Override

  2. protected void onCreate(Bundle savedInstanceState) {

  3.     super.onCreate(savedInstanceState);

  4.     setContentView(R.layout.activity_main);

  5.     edtWidth = findViewById(R.id.edt_width);

  6.     edtHeight = findViewById(R.id.edt_height);

  7.     edtLength = findViewById(R.id.edt_length);

  8.     btnCalculate = findViewById(R.id.btn_calculate);

  9.     tvResult = findViewById(R.id.tv_result);

  10.  

  11.     btnCalculate.setOnClickListener(this);

  12. }




  1. override fun onCreate(savedInstanceState: Bundle?) {

  2.     super.onCreate(savedInstanceState)

  3.     setContentView(R.layout.activity_main)

  4.  

  5.     edtWidth = findViewById(R.id.edt_width)

  6.     edtHeight = findViewById(R.id.edt_height)

  7.     edtLength = findViewById(R.id.edt_length)

  8.     btnCalculate = findViewById(R.id.btn_calculate)

  9.     tvResult = findViewById(R.id.tv_result)

  10.  

  11.     btnCalculate.setOnClickListener(this)

  12. }


Metode onCreate() merupakan metode utama pada activity. Di sinilah kita dapat mengatur layout xml. 
Semua proses inisialisasi komponen yang digunakan akan dijalankan di sini. Pada metode ini kita casting semua komponen view yang kita telah deklarasikan sebelumnya, agar dapat kita manipulasi.
SetContentView


  1. setContentView(R.layout.activity_main);




  1. setContentView(R.layout.activity_main)


Maksud baris di atas adalah kelas MainActivity akan menampilkan tampilan yang berasal dari layout activity_main.xml.
Casting View


  1. edtWidth = findViewById(R.id.edt_width);




  1. edtWidth = findViewById(R.id.edt_width)


Maksud dari baris di atas adalah obyek EditTextedtWidth disesuaikan (cast) dengan komponen EditText ber-ID edt_width di layout activity_main.xml melalui metode findViewById().
SetOnClickListener




  1. btnCalculate.setOnClickListener(this); 





  1. btnCalculate.setOnClickListener(this)


Kita memasang event click listener untuk obyek btnCalculate sehingga sebuah aksi dapat dijalankan ketika obyek tersebut diklik. 
Keyword this merujuk pada obyek Activity saat ini yang telah mengimplementasikan listener OnClickListener sebelumnya.  
Sehingga ketika btnCalculate diklik, maka fungsi onClick akan dipanggil dan melukakan proses yang ada di dalamnya.
Mengambil value dari EditText




  1. String inputLength = edtLength.getText().toString().trim();

  2. String inputWidth = edtWidth.getText().toString().trim();

  3. String inputHeight = edtHeight.getText().toString().trim();





  1. val inputLength = edtLength.text.toString().trim()

  2. val inputWidth = edtWidth.text.toString().trim()

  3. val inputHeight = edtHeight.text.toString().trim()


Sintaks .text.toString() di atas berfungsi untuk mengambil isi dari sebuah EditText kemudian menyimpannya dalam sebuah variabel. Tambahan .trim() berfungsi untuk menghiraukan spasi jika ada, sehingga nilai yang didapat hanya berupa angka.
Cek inputan yang kosong




  1. boolean isEmptyFields = false;

  2. boolean isInvalidDouble = false;

  3.  

  4. if (TextUtils.isEmpty(inputLength)) {

  5.     isEmptyFields = true;

  6.     edtLength.setError("Field ini tidak boleh kosong");

  7. }

  8.  

  9. if (TextUtils.isEmpty(inputWidth)) {

  10.     isEmptyFields = true;

  11.     edtWidth.setError("Field ini tidak boleh kosong");

  12. }

  13.  

  14. if (TextUtils.isEmpty(inputHeight)) {

  15.     isEmptyFields = true;

  16.     edtHeight.setError("Field ini tidak boleh kosong");

  17. }





  1. var isEmptyFields = false

  2. var isInvalidDouble = false

  3.  

  4. when {

  5.     inputLength.isEmpty() -> {

  6.         isEmptyFields = true

  7.         edtLength.error = "Field ini tidak boleh kosong"

  8.     }

  9.     inputWidth.isEmpty() -> {

  10.         isEmptyFields = true

  11.         edtWidth.error = "Field ini tidak boleh kosong"

  12.     }

  13.     inputHeight.isEmpty() -> {

  14.         isEmptyFields = true

  15.         edtHeight.error = "Field ini tidak boleh kosong"

  16.     }

  17. }


Sintaks .isEmpty() berfungsi untuk mengecek apakah inputan dari Editext itu masih kosong. 
Jika iya, maka kita akan menampilkan pesan error dengan menggunakan .setError("Field ini tidak boleh kosong") dan mengganti variabel Boolean isEmptyField menjadi true supaya bisa lanjut ke proses selanjutnya.
Validasi input yang bukan angka


  1. Double length = toDouble(inputLength);

  2. Double width = toDouble(inputWidth);

  3. Double height = toDouble(inputHeight);

  4.  

  5. if (length == null) {

  6.     isInvalidDouble = true;

  7.     edtLength.setError("Field ini harus berupa nomer yang valid");

  8. }

  9.  

  10. if (width == null) {

  11.     isInvalidDouble = true;

  12.     edtWidth.setError("Field ini harus berupa nomer yang valid");

  13. }

  14.  

  15. if (height == null) {

  16.     isInvalidDouble = true;

  17.     edtHeight.setError("Field ini harus berupa nomer yang valid");

  18. }

  19.  

  20. ...

  21.  

  22. private Double toDouble(String str) {

  23.     try {

  24.         return Double.valueOf(str);

  25.     } catch (NumberFormatException e) {

  26.         return null;

  27.     }

  28. }




  1. val length = toDouble(inputLength)

  2. val width = toDouble(inputWidth)

  3. val height = toDouble(inputHeight)

  4.  

  5. when {

  6.     length == null -> {

  7.         isInvalidDouble = true

  8.         edtLength.error = "Field ini harus berupa nomer yang valid"

  9.     }

  10.     width == null -> {

  11.         isInvalidDouble = true

  12.         edtWidth.error = "Field ini harus berupa nomer yang valid"

  13.     }

  14.     height == null -> {

  15.         isInvalidDouble = true

  16.         edtHeight.error = "Field ini harus berupa nomer yang valid"

  17.     }

  18. }

  19.  

  20. ...

  21.  

  22. private fun toDouble(str: String): Double? {

  23.     return try {

  24.         str.toDouble()

  25.     } catch (e: NumberFormatException) {

  26.         null

  27.     }

  28. }


toDouble() adalah sebuah fungsi yang kita buat sendiri di luar onCreate untuk merubah data inputan yang sebelumnya berupa String menjadi Double, hal ini karena secara default input di EditText tipe datanya berupa String, padahal kita perlu dalam bentuk Double supaya bisa dilakukan proses perhitungan. 
Fungsi ini juga sekaligus mengecek apakah inputan yang dimasukkan berupa angka atau bukan, jika bukan maka ditaampilkan pesan error.
Menampilkan data ke EditText




  1. if (!isEmptyFields && !isInvalidDouble) {

  2.     double volume = length * width * height;

  3.     tvResult.setText(String.valueOf(volume));

  4. }





  1. if (!isEmptyFields && !isInvalidDouble) {

  2.     val volume = length as Double * width as Double * height as Double

  3.     tvResult.text = volume.toString()

  4. }


Sintaks !isEmptyFields memiliki arti "jika semua inputan tidak kosong", dan !isInvalidDouble memiliki arti "jika semua inputan berisi angka". 
Jika kedua kondisi tersebut terpenuhi, maka langkah selanjutnya yaitu melakukan proses perhitungan dan kemudian kita tampilkan pada TextView tvResult dengan menggunakan .setText()
Di sini dapat kita lihat bahwa kita perlu merubah datanya yang sebelumnya Double menjadi String, karena untuk menampilkan data dengan setText() harus berupa String.
Pembahasan saveInstanceState




  1. @Override

  2. protected void onSaveInstanceState(Bundle outState) {

  3.     super.onSaveInstanceState(outState);

  4.     outState.putString(STATE_RESULT, tvResult.getText().toString());

  5. }





  1. override fun onSaveInstanceState(outState: Bundle) {

  2.     super.onSaveInstanceState(outState)

  3.     outState.putString(STATE_RESULT, tvResult.text.toString())

  4. }


Perhatikan metode onSaveInstanceState
Di dalam metode tersebut, hasil perhitungan yang ditampilkan pada tvResult dimasukkan pada bundle kemudian disimpan isinya. 
Untuk menyimpan data disini menggunakan konsep Key-Value, dengan STATE_RESULT sebagai key dan isi dari tvResult sebagai value. Fungsi onSaveInstanceState akan dipanggil secara otomatis sebelum sebuah Activity hancur. 
Di sini kita perlu menambahkan onSaveInstanceState karena ketika orientasi berubah, Activity tersebut akan di-destroy dan memanggil fungsi onCreate lagi, sehingga kita perlu menyimpan nilai hasil perhitungan tersebut supaya data tetap terjaga dan tidak hilang ketika orientasi berubah.


  1. if (savedInstanceState != null){

  2.     String hasil = savedInstanceState.getString(STATE_RESULT);

  3.     tvResult.setText(hasil);

  4. }




  1. if (savedInstanceState != null) {

  2.     val result = savedInstanceState.getString(STATE_RESULT) as String

  3.     tvResult.text = result

  4. }


Pada onCreate inilah kita menggunakan nilai bundle yang telah kita simpan sebelumnya pada onSaveInstanceState. Nilai tersebut kita dapatkan dengan menggunakan Key yang sama dengan saat menyimpan, yaitu STATE_RESULT. Kemudian kita isikan kembali pada tvResult.
Selamat! Anda telah berhasil membuat dan menjalankan latihan Android pertama di peranti atau emulator. Silakan lanjut ke codelab berikutnya.
Anda dapat mengunduh source code materi ini di tautan berikut: