Android Vs Laravel # Part 2 Membuat Aplikasi Android CRUD pada Android Studio - Mengambil Data Dari API Service Laravel
PART 1 - MENGAMBIL DATA DARI API SERVICE
Salah satu hal yang tidak boleh dilupakan saat kita mengembangkan sebuah aplikasi adalah bagaimana caranya agar aplikasi kita dapat berkomunikasi dengan jaringan internet. Hampir semua aplikasi seperti sosial media, messenger, news, dan lainnya, pasti membutuhkan koneksi internet untuk transaksi data dengan server mereka.
Pada modul sebelumnya, Anda sudah belajar membuat aplikasi yang bisa menampilkan data berupa array ke dalam RecyclerView dengan menerapkan fitur Kotlin Android Extensions, Anko Commons, dan juga Anko Layout. Sekarang saatnya Anda membuat aplikasi yang bisa menampilkan data dari sebuah API. Kita akan menggunakan API dari TheSportDB. Dengan API tersebut Anda bisa membuat aplikasi untuk menampilkan daftar tim sepak bola, jadwal pertandingan sepak bola, live score, dsb. Untuk bisa melakukan permintaan data dari sebuah API, Anda bisa menggunakan library semacam Retrofit atau yang lainnya.
Melakukan request data ke sebuah API ketika mengembangkan aplikasi Android bisa dibilang sulit kalau kita tidak menggunakan library pihak ketiga. Anda akan berurusan dengan HttpURLConnection, BufferedReader, dan teman-temannya. Sebagai contoh ketika Anda ingin mendapatkan respon dari API, Anda perlu menuliskan kode berikut:
1. URL url = new URL("http://www.example.com/api/");
2. HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
3. try {
4. InputStream in = new BufferedInputStream(urlConnection.getInputStream());
5. readStream(in);
6. } finally {
7. urlConnection.disconnect();
8. }
Tentunya kode di atas tidak akan cukup jika nantinya kita membutuhkan respon yang lebih spesifik. Namun Anda tidak perlu khawatir, karena Kotlin menyediakan beberapa extension functions yang bisa mempermudah dan menyederhanakan suatu fungsi. Salah satunya adalah readText, sebuah extension functions yang bisa digunakan untuk request data dari API. Fungsi tersebut cukup bagus untuk menangani permintaan data yang sederhana, namun tidak direkomendasikan jika Anda ingin melakukan permintaan data yang besar.
Untuk menerapkan fungsi readText Anda bisa membuat kelas baru, misalnya seperti berikut:
1. class ApiRepository {
2.
3. fun doRequest(url: String): String {
4. return URL(url).readText()
5. }
6. }
readText() akan membaca url sebagai string. Kemudian fungsi doRequest() di atas akan mengembalikan respon yang merupakan hasil request dari sebuah API.
Membuat Aplikasi Football Club
Pada latihan kali ini, Anda akan membuat sebuah aplikasi yang bisa menampilkan data dari API. Aplikasi yang akan dibuat adalah Football Club, yang memanfaatkan API dari TheSportDB untuk menampilkan daftar tim sepak bola berdasarkan liga yang telah ditentukan. Di dalam TheSportDB terdapat beberapa endpoint yang sangat mudah untuk digunakan. Untuk melihat daftar endpoint yang tersedia, Anda bisa membuka tautan berikut ini: https://www.thesportsdb.com/api.php. Aplikasi yang akan kita buat mempunyai beberapa use cases seperti berikut:
· Pengguna dapat melihat daftar tim dalam suatu liga.
· Aplikasi dapat menampilkan daftar nama tim dilengkapi dengan logo tim.
Kurang lebih hasil aplikasi yang diharapkan menyerupai gambar di bawah ini:
Membuat Proyek Baru
Buatlah proyek baru pada Android Studio 3.1.2. Jangan lupa aktifkan Kotlin dan Anko Support.
Menambahkan Dependensi
Kita akan membutuhkan beberapa dependensi seperti Android Support Library, Anko, dan juga Gson sebagai libraryuntuk mengubah objek menjadi JSON. Tambahkanlah semua dependensi yang dibutuhkan ke dalam build.gradle.
1. implementation 'com.android.support:appcompat-v7:27.1.1'
2. implementation 'com.android.support:design:27.1.1'
3.
4. //anko
5. implementation "org.jetbrains.anko:anko:$anko_version"
6. implementation "org.jetbrains.anko:anko-design:$anko_version"
7.
8. // RecyclerView-v7
9. implementation "org.jetbrains.anko:anko-recyclerview-v7:$anko_version"
10. implementation "org.jetbrains.anko:anko-recyclerview-v7-coroutines:$anko_version"
11.
12. implementation 'com.squareup.picasso:picasso:2.71828'
13. implementation 'com.google.code.gson:gson:2.8.5'
Jangan lupa untuk mensinkronisasi proyek.
Mendesain Tampilan
Selanjutnya, kita akan mendesain tampilan utama dari aplikasi. Anda perlu menambahkan sebuah RecyclerView dan beberapa komponen view lainnya seperti Spinner, SwipeRefreshLayout, ProgressBar, ImageView, dan juga TextView. Buka MainActivity dan hapus fungsi setContentView karena kita akan menggunakan Anko Layout dalam mendesain tampilan. Deklarasikan beberapa view tersebut sebagai variabel lateinit:
1. private lateinit var listTeam: RecyclerView
2. private lateinit var progressBar: ProgressBar
3. private lateinit var swipeRefresh: SwipeRefreshLayout
4. private lateinit var spinner: Spinner
lateinit digunakan untuk menginisialisasi nilai variabel sebelum Anda mengaksesnya. Kemudian tambahkan kode berikut ke dalam method onCreate:
1. linearLayout {
2. lparams (width = matchParent, height = wrapContent)
3. orientation = LinearLayout.VERTICAL
4. topPadding = dip(16)
5. leftPadding = dip(16)
6. rightPadding = dip(16)
7.
8. spinner = spinner ()
9. swipeRefresh = swipeRefreshLayout {
10. setColorSchemeResources(colorAccent,
11. android.R.color.holo_green_light,
12. android.R.color.holo_orange_light,
13. android.R.color.holo_red_light)
14.
15. relativeLayout{
16. lparams (width = matchParent, height = wrapContent)
17.
18. listTeam = recyclerView {
19. lparams (width = matchParent, height = wrapContent)
20. layoutManager = LinearLayoutManager(ctx)
21. }
22.
23. progressBar = progressBar {
24. }.lparams{
25. centerHorizontally()
26. }
27. }
28. }
29. }
Dengan Anko Layout di atas, Anda telah menambahkan sebuah LinearLayout sebagai parent layout yang di dalamnya terdapat beberapa view yang dibungkus dalam SwipeRefreshLayout.
Mengatur Network Service
Setelah berhasil mendesain tampilan utama dari aplikasi, kita akan membuat beberapa kelas. Fungsinya, untuk mengatur layanan jaringan (network service) yang akan digunakan untuk mendapatkan data dari server.
Tambahkan juga buildConfigField pada defaultConfig di dalam berkas build.gradle untuk menyimpan BASE_URLdan API_KEY dari TheSportDB.
Tambahkan juga buildConfigField pada defaultConfig di dalam berkas build.gradle untuk menyimpan BASE_URLdan API_KEY dari TheSportDB.
1. buildConfigField "String", "BASE_URL", "\"https://www.thesportsdb.com/\""
2. buildConfigField "String", "TSDB_API_KEY", "\"1\""
Bangun kembali (rebuild) proyek dan buat kelas baru dengan nama ApiRespository lalu tambahkan fungsi doRequestyang di dalamnya terdapat extension functions readText untuk membaca url seperti berikut:
1. class ApiRepository {
2.
3. fun doRequest(url: String): String {
4. return URL(url).readText()
5. }
6. }
Kemudian buat kelas objek baru lagi dengan nama TheSportDBApi yang di dalamnya terdapat sebuah fungsi untuk menampung endpoint yang akan digunakan. Kita akan menggunakan endpoint /search_all_team.php?id=+LEAGUE_NAME untuk mendapatkan data daftar tim berdasarkan liga yang dipilih.
1. object TheSportDBApi {
2. fun getTeams(league: String?): String {
3. return BuildConfig.BASE_URL + "api/v1/json/${BuildConfig.TSDB_API_KEY}" + "/search_all_teams.php?l=" + league
4. }
5. }
Penulisan fungsi di atas bisa juga dilakukan dengan cara yang lebih sederhana, yaitu dengan memanfaatkan fungsi Uri.Builder dari Android. Sehingga, kodenya menjadi seperti berikut:
1. fun getTeams(league: String?): String {
2. return Uri.parse(BuildConfig.BASE_URL).buildUpon()
3. .appendPath("api")
4. .appendPath("v1")
5. .appendPath("json")
6. .appendPath(BuildConfig.TSDB_API_KEY)
7. .appendPath("search_all_teams.php")
8. .appendQueryParameter("l", league)
9. .build()
10. .toString()
11. }
Dengan begitu kode akan terlihat lebih rapi.
Selanjutnya, Anda perlu membuat data class untuk menampung respon dari API. Untuk mengetahui respon tersebut, Anda bisa mengakses endpoint-nya pada Postman seperti gambar di bawah ini:
Setelah mengetahui respon tersebut, buatlah 2 (dua) data class berisi objek yang dibutuhkan.
Team.Kt:
1. data class Team(
2. @SerializedName("idTeam")
3. var teamId: String? = null,
4.
5. @SerializedName("strTeam")
6. var teamName: String? = null,
7.
8. @SerializedName("strTeamBadge")
9. var teamBadge: String? = null
10. )
Pada data class ini, setiap objek diberi anotasi @SerializedName. Parameter (nilai) dari anotasi tersebut adalah nama yang akan digunakan pada saat mengkomersialkan dan deserializing objek. Misalnya, field teamNamedirepresentasikan sebagai strTeam di JSON.TeamResponse.Kt:
1. data class TeamResponse(
2. val teams: List<Team>)
Kelas ini merupakan data class yang akan menampung objek berupa list dari data class sebelumnya.
Menerapkan Business Logic
Dalam proyek ini, kita akan mencoba menerapkan MVP (Model View Presenter) sebagai pola desainnya (design pattern). MVP adalah sebuah pola desain yang memungkinkan kita memisahkan antara logika bisnis dari aplikasi dengan view.
Untuk menerapkan MVP, kita akan membutuhkan 3 (tiga) komponen utama dari pattern tersebut yaitu pertama, Modelyang berfungsi untuk mengelola data; kedua, View untuk mengatur tampilan; dan ketiga, Presenter untuk menjembatani antara model dan view.
Sebelumnya, Anda sudah membuat model, yaitu 2 (dua) data class Team dan TeamResponse. Sekarang Anda tinggal menambahkan view dan presenter untuk melengkapinya.
Untuk menerapkan MVP, kita akan membutuhkan 3 (tiga) komponen utama dari pattern tersebut yaitu pertama, Modelyang berfungsi untuk mengelola data; kedua, View untuk mengatur tampilan; dan ketiga, Presenter untuk menjembatani antara model dan view.
Sebelumnya, Anda sudah membuat model, yaitu 2 (dua) data class Team dan TeamResponse. Sekarang Anda tinggal menambahkan view dan presenter untuk melengkapinya.
Kita akan menjadikan MainActivity sebagai view. Untuk itu, kita membutuhkan sebuah interface dan sebuah presenter. Buatlah interface baru dengan nama MainView yang berisi beberapa fungsi berikut:
1. interface MainView {
2. fun showLoading()
3. fun hideLoading()
4. fun showTeamList(data: List<Team>)
5. }
Kemudian buat kelas baru yang akan berperan sebagai presenter yang dilengkapi dengan beberapa constructor seperti berikut:
1. class MainPresenter(private val view: MainView,
2. private val apiRepository: ApiRepository,
3. private val gson: Gson) {
4. }
Di dalam presenter tersebut, kita perlu menambahkan beberapa behaviour, antara lain:
· Ketika presenter sedang menunggu respon, ProgressBar akan ditampilkan.
· Ketika respon berhasil didapatkan, ProgressBar akan hilang dan data akan ditampilkan ke dalam view.
Untuk menerapkan behaviour di atas, buatlah fungsi getTeamList di dalam presenter tersebut:
1. fun getTeamList(league: String?) {
2. view.showLoading()
3. doAsync {
4. val data = gson.fromJson(apiRepository
5. .doRequest(TheSportDBApi.getTeams(league)),
6. TeamResponse::class.java
7. )
8.
9. uiThread {
10. view.hideLoading()
11. view.showTeamList(data.teams)
12. }
13. }
14. }
Ketika fungsi di atas dijalankan, otomatis juga akan memanggil fungsi showLoading dan doAsync. Fungsi doAsyncdari Anko bisa digunakan untuk menjalankan asynchronous task. Ia akan memanggil fungsi doRequest, dan jika berhasil data akan ditampilkan oleh uiThread.
Membuat RecyclerView Adapter
Untuk menampilkan list data pada RecyclerView, kita membutuhkan sebuah adapter yang akan mengatur semua elemen pada list tersebut. Di dalam adapter ini kita perlu menambahkan sebuah holder yang akan digunakan untuk menyatukan semua data ke dalam view. Selain itu, kita juga bisa mendesain tampilan dari item list menggunakan Anko Layout di dalam adapter.
Buatlah kelas baru bernama MainAdapter dengan parameter seperti berikut:
1. class MainAdapter (private val teams: List<Team>) {
2.
3. }
Setelah itu tambahkan kelas dengan nama TeamViewHolder yang mewarisi kelas RecyclerView.ViewHolder. Kelas tersebut akan kita jadikan parameter untuk kelas RecyclerView.Adapter yang kita wariskan ke kelas MainAdapter. Alhasil, strukturnya menjadi seperti ini:
1. class MainAdapter (private val teams: List<Team>)
2. : RecyclerView.Adapter<TeamViewHolder>(){
3.
4.
5. }
6.
7. class TeamViewHolder(view: View) : RecyclerView.ViewHolder(view){
8.
9.
10. fun bindItem(teams: Team) {
11.
12. }
13. }
Pada kondisi ini, kelas MainAdapter pasti akan terdeteksi sebagai suatu kesalahan. Sebabnya, kita belum menerapkan semua anggota dari kelas RecyclerView.Adapter. Tekan ALT + Enter pada baris yang eror dan terapkan semua anggotanya:
1. class MainAdapter (private val teams: List<Te>am)
2. : RecyclerView.Adapter<TeamViewHolder>(){
3. override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): TeamViewHolder {
4. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
5. }
6.
7. override fun getItemCount(): Int {
8. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
9. }
10.
11. override fun onBindViewHolder(holder: TeamViewHolder?, position: Int) {
12. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
13. }
14.
15. }
16.
17. class TeamViewHolder(view: View) : RecyclerView.ViewHolder(view){
18.
19.
20. fun bindItem(teams: Team) {
21.
22. }
23. }
Masih di kelas MainAdapter kita akan mendesain tampilan dari item yang akan dimasukkan ke dalam RecyclerView. Kita perlu menambahkan sebuah TextView dan ImageView. Berikut adalah kode yang perlu ditambahkan menggunakan Anko Layout:
1. class TeamUI : AnkoComponent<ViewGroup> {
2. override fun createView(ui: AnkoContext<ViewGroup>): View {
3. return with(ui) {
4. linearLayout {
5. lparams(width = matchParent, height = wrapContent)
6. padding = dip(16)
7. orientation = LinearLayout.HORIZONTAL
8.
9. imageView {
10. id = R.id.team_badge
11. }.lparams{
12. height = dip(50)
13. width = dip(50)
14. }
15.
16. textView {
17. id = R.id.team_name
18. textSize = 16f
19. }.lparams{
20. margin = dip(15)
21. }
22.
23. }
24. }
25. }
26.
27. }
Pada masing-masing komponen view di atas, terdapat atribut id. Ia akan eror karena kita belum mendefinisikan sebuah id value resource untuk menampung kumpulan id. Untuk menambahkannya, tekan ALT + Enter pada setiap id dan pilih create id value resource. Lalu akan muncul window seperti berikut :
Tekan OK dan atribut id akan ditambahkan ke berkasids.xml:
1. <?xml version="1.0" encoding="utf-8"?>
2. <resources>
3. <item name="team_badge" type="id" />
4. <item name="team_name" type="id" />
5. </resources>
Dengan begitu semua view di atas sudah bisa kita akses pada ViewHolder. Deklarasikan semua view yang dibutuhkan dengan menambahkan variabel berikut di dalam kelas TeamViewHolder:
1. private val teamBadge: ImageView = view.find(team_badge)
2. private val teamName: TextView = view.find(team_name)
Setelah itu kita bisa mengumpulkan objek dari data class ke masing-masing view tersebut:
1. fun bindItem(teams: Team) {
2. Picasso.get().load(teams.teamBadge).into(teamBadge)
3. teamName.text = teams.teamName
4. }
Dengan begitu, tampilan yang sudah kita desain akan ditampilkan saat method onCreateViewHolder dijalankan.
Pada method getItemCount kita definisikan teams.size sebagai nilainya:
1. override fun getItemCount(): Int = teams.size
Kemudian pada method onBindViewHolder tambahkan kode berikut untuk menampilkan data pada posisi yang telah ditentukan :
1. holder.bindItem(teams[position])
Sampai di sini kita sudah selesai membuat sebuah RecyclerView adapter. Kode keseluruhan dari adapter tersebut kurang lebih seperti berikut :
1. class MainAdapter(private val teams: List<Team>)
2. : RecyclerView.Adapter<TeamViewHolder>() {
3.
4. override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TeamViewHolder {
5. return TeamViewHolder(TeamUI().createView(AnkoContext.create(parent.context, parent)))
6. }
7.
8. override fun onBindViewHolder(holder: TeamViewHolder, position: Int) {
9. holder.bindItem(teams[position])
10. }
11.
12. override fun getItemCount(): Int = teams.size
13.
14. }
15.
16. class TeamUI : AnkoComponent<ViewGroup> {
17. override fun createView(ui: AnkoContext<ViewGroup>): View {
18. return with(ui) {
19. linearLayout {
20. lparams(width = matchParent, height = wrapContent)
21. padding = dip(16)
22. orientation = LinearLayout.HORIZONTAL
23.
24. imageView {
25. id = R.id.team_badge
26. }.lparams{
27. height = dip(50)
28. width = dip(50)
29. }
30.
31. textView {
32. id = R.id.team_name
33. textSize = 16f
34. }.lparams{
35. margin = dip(15)
36. }
37.
38. }
39. }
40. }
41.
42. }
43.
44. class TeamViewHolder(view: View) : RecyclerView.ViewHolder(view){
45.
46. private val teamBadge: ImageView = view.find(team_badge)
47. private val teamName: TextView = view.find(team_name)
48.
49. fun bindItem(teams: Team) {
50. Picasso.get().load(teams.teamBadge).into(teamBadge)
51. teamName.text = teams.teamName
52. }
53. }
Menyelesaikan Aplikasi Football Club
Setelah berhasil menerapkan semuanya, untuk tahap terakhir kita perlu menerapkan presenter dan adapter yang sudah dibuat ke dalam MainActivity. Tambahkan beberapa variabel berikut:
1. private var teams: MutableList<Team> = mutableListOf()
2. private lateinit var presenter: MainPresenter
3. private lateinit var adapter: MainAdapter
Lalu di dalam method onCreate, tambahkan kode berikut:
1. adapter = MainAdapter(teams)
2. listTeam.adapter = adapter
3.
4. val request = ApiRepository()
5. val gson = Gson()
6. presenter = MainPresenter(this, request, gson)
Setelah mendeklarasikan adapter, presenter, dan beberapa komponen yang dibutuhkan, sekarang Anda sudah bisa memanggil fungsi getTeamList yang ada pada presenter. Fungsi tersebut membutuhkan parameter berupa string yang merupakan nama dari liga yang dipilih. Kita akan memilih nama liga tersebut dari sebuah Spinner. Deklarasikan sebuah variabel leagueName pada MainActivity:
1. private lateinit var leagueName: String
Kemudian tambahkan kode berikut pada method onCreate untuk mengatur SpinnerAdapter:
1. val spinnerItems = resources.getStringArray(league)
2. val spinnerAdapter = ArrayAdapter(ctx, android.R.layout.simple_spinner_dropdown_item, spinnerItems)
3. spinner.adapter = spinnerAdapter
Pastikan sebelumnya Anda sudah membuat Array dari nama-nama liga yang diinginkan pada berkas strings.xml:
1. <array name="league">
2. <item>English Premier League</item>
3. <item>English League Championship</item>
4. <item>German Bundesliga</item>
5. <item>Italian Serie A</item>
6. <item>French Ligue 1</item>
7. <item>Spanish La Liga</item>
8. </array>
Untuk memanggil fungsi getListTeam pada presenter ketika nama liga dipilih, Anda bisa memanggilnya di dalam onItemSelectedListener pada Spinner tersebut:
1. spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
2. override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
3. leagueName = spinner.selectedItem.toString()
4. presenter.getTeamList(leagueName)
5. }
6.
7. override fun onNothingSelected(parent: AdapterView<*>) {}
8. }
Fungsi getListTeam memerlukan semua fungsi yang ada pada interface MainView. Oleh karena itu, MainActivity perlu menerapkan interface tersebut beserta semua anggotanya.
1. class MainActivity : AppCompatActivity(), MainView {
2.
3. private var teams: MutableList<Team> = mutableListOf()
4. private lateinit var presenter: MainPresenter
5. private lateinit var adapter: MainAdapter
6. private lateinit var listTeam: RecyclerView
7. private lateinit var progressBar: ProgressBar
8. private lateinit var swipeRefresh: SwipeRefreshLayout
9. private lateinit var spinner: Spinner
10. private lateinit var leagueName: String
11.
12.
13. override fun onCreate(savedInstanceState: Bundle?) {...}
14.
15.
16. override fun showLoading() {
17. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
18. }
19.
20. override fun hideLoading() {
21. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
22. }
23.
24. override fun showTeamList(data: List<Team>) {
25. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
26. }
27.
28. }
Kita belum menerapkan apapun pada ketiga anggota dari interface MainView tersebut. Method showLoading dan hideLoading akan kita gunakan untuk mengatur ProgressBar. Oleh karena itu, kita akan membuat extensions functionbaru untuk melakukannya. Buatlah file Utils.Kt dan tambahkan 2 (dua) fungsi berikut:
1. fun View.visible() {
2. visibility = View.VISIBLE
3. }
4.
5. fun View.invisible() {
6. visibility = View.INVISIBLE
7. }
Fungsi visible() digunakan untuk menampilkan ProgressBar, sedangkan invisible() untuk menyembunyikannya. Kita bisa menerapkannya pada method showLoading dan hideLoading:
1. override fun showLoading() {
2. progressBar.visible()
3. }
4.
5. override fun hideLoading() {
6. progressBar.invisible()
7. }
Kemudian pada method showTeamList kita perlu menambahkan kode berikut untuk memasukkan semua data yang didapatkan dari server kedalam data class Team:
1. override fun showTeamList(data: List<Team>) {
2. swipeRefresh.isRefreshing = false
3. teams.clear()
4. teams.addAll(data)
5. adapter.notifyDataSetChanged()
6. }
Pada kelas MainActivity, kita juga memiliki SwipeRefreshLayout yang belum kita terapkan fungsinya. Komponen ini akan kita gunakan untuk melakukan penyegaran data pada aplikasi. Untuk menerapkannya, tambahkan fungsi onRefresh dan panggil presenter.getTeamList() di dalamnya.
1. swipeRefresh.onRefresh {
2. presenter.getTeamList(leagueName)
3. }
Jangan lupa untuk menambahkan swipeRefresh.isRefreshing = false ketika data sudah berhasil diperbarui.
Selesai, keseluruhan kode pada MainActivity kurang lebih seperti berikut:
1. class MainActivity : AppCompatActivity(), MainView {
2. private var teams: MutableList<Team> = mutableListOf()
3. private lateinit var presenter: MainPresenter
4. private lateinit var adapter: MainAdapter
5. private lateinit var listTeam: RecyclerView
6. private lateinit var progressBar: ProgressBar
7. private lateinit var swipeRefresh: SwipeRefreshLayout
8. private lateinit var spinner: Spinner
9. private lateinit var leagueName: String
10.
11. override fun onCreate(savedInstanceState: Bundle?) {
12. super.onCreate(savedInstanceState)
13. linearLayout {
14. lparams (width = matchParent, height = wrapContent)
15. orientation = LinearLayout.VERTICAL
16. topPadding = dip(16)
17. leftPadding = dip(16)
18. rightPadding = dip(16)
19.
20. spinner = spinner ()
21. swipeRefresh = swipeRefreshLayout {
22. setColorSchemeResources(colorAccent,
23. android.R.color.holo_green_light,
24. android.R.color.holo_orange_light,
25. android.R.color.holo_red_light)
26.
27. relativeLayout{
28. lparams (width = matchParent, height = wrapContent)
29.
30. listTeam = recyclerView {
31. lparams (width = matchParent, height = wrapContent)
32. layoutManager = LinearLayoutManager(ctx)
33. }
34.
35. progressBar = progressBar {
36. }.lparams{
37. centerHorizontally()
38. }
39. }
40. }
41. }
42.
43. val spinnerItems = resources.getStringArray(league)
44. val spinnerAdapter = ArrayAdapter(ctx, android.R.layout.simple_spinner_dropdown_item, spinnerItems)
45. spinner.adapter = spinnerAdapter
46.
47. adapter = MainAdapter(teams)
48. listTeam.adapter = adapter
49.
50. val request = ApiRepository()
51. val gson = Gson()
52. presenter = MainPresenter(this, request, gson)
53.
54. spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
55. override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
56. leagueName = spinner.selectedItem.toString()
57. presenter.getTeamList(leagueName)
58. }
59.
60. override fun onNothingSelected(parent: AdapterView<*>) {}
61. }
62.
63. swipeRefresh.onRefresh {
64. presenter.getTeamList(leagueName)
65. }
66. }
67.
68. override fun showLoading() {
69. progressBar.visible()
70. }
71.
72. override fun hideLoading() {
73. progressBar.invisible()
74. }
75.
76. override fun showTeamList(data: List<Team>) {
77. swipeRefresh.isRefreshing = false
78. teams.clear()
79. teams.addAll(data)
80. adapter.notifyDataSetChanged()
81. }
82.
83. }
Terakhir, pastikan Anda sudah
menambahkan internet permission pada AndroidManifest:
menambahkan internet permission pada AndroidManifest:
1. <uses-permission android:name="android.permission.INTERNET"/>
Android Vs Laravel # Part 2 Membuat Aplikasi Android CRUD pada Android Studio - Mengambil Data Dari API Service Laravel
Reviewed by andre septian
on
Senin, Februari 10, 2020
Rating:
Tidak ada komentar: