Aplikasi Covid-19 using MVP
Pada kali ini saya akan membuat Aplikasi Covid-19, di aplikasi ini kita dapat melihat seberapa banyak orang yg telah terkena virus ini, dan kita juga bisa tahu grafik setiap negara yg telah terkena virus covid-19. Lagsung saja kita mulai.
Syarat:
- Menggunakan Android Studio
- Menggunakan bahasa Kotlin
- Menyiapkan Emulator atau Smartphone degan versi android diatas 16 atau Jelly bean
Persiapan
Pilih Empty Activity dan tekan next
Buat nama project Covid-19 MVP atau sesuka anda, lalu tekan finish
Buka build.gradle(Module: app)
// depedency
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation 'com.google.android.material:material:1.1.0'
implementation 'de.hdodenhof:circleimageview:3.1.0'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation 'com.github.bumptech.glide:glide:4.8.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
implementation 'com.amitshekhar.android:android-networking:1.0.2'
Lalu tambahakan kode berikut, kode ini berfungsi dibutuhkan untuk project kali ini
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
Masih didalam module build.gradel(Module: app) tambahkan compileOptions, dan letakan diatas buildType
maven { url ‘https://jitpack.io' }
Dan tambahkan kode berikut didalam build.gradel(Project: {Nama_Aplikasi}), dan letakan di allproject
Setelah itu tekan tombol sync dipojok kanan atas, dan tunggu sebentar karen Android Studio akan mendownload file yg dibutuhkan. Apabila anda sudah pernah menggunakan depedncy tersebut sinkronisasi tidak akan berjalan lama
Buat lah package seperti berikut
Setelah itu buat lah activity ChartCountryActivity. Kemudian buka lah activity_main.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.MainActivity">
<LinearLayout
android:id="@+id/lay_linear1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginStart="@dimen/dp8"
android:layout_marginEnd="@dimen/dp8">
<androidx.appcompat.widget.SearchView
android:id="@+id/search_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp8"
android:layout_marginBottom="@dimen/dp8"
android:layout_weight="1"
android:background="@drawable/box_search_country"
app:queryHint="Cari Negara"
android:textCursorDrawable="@null"
app:iconifiedByDefault="false"
app:queryBackground="@null"
app:actionViewClass="android.widget.SearchView"/>
<Button
android:id="@+id/btn_sequence"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp2"
android:layout_marginStart="@dimen/dp2"
android:layout_marginTop="@dimen/dp8"
android:layout_marginBottom="@dimen/dp8"
android:background="@drawable/ic_sequence"
android:layout_weight="5"/>
</LinearLayout>
<LinearLayout
android:id="@+id/lay_globe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/lay_linear1"
android:layout_marginStart="@dimen/dp8"
android:layout_marginEnd="@dimen/dp8"
android:background="@drawable/bg_blue"
android:orientation="horizontal"
android:baselineAligned="false">
<!-- Region text confirmed-->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp8"
android:layout_marginEnd="@dimen/dp8"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="16sp"
android:layout_marginTop="@dimen/dp8"
android:text="@string/confirmed"/>
<TextView
android:id="@+id/tv_confirmed_globe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginBottom="@dimen/dp8"
android:text="-"/>
</LinearLayout>
<!-- Endregion-->
<!-- Region text recovered-->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp8"
android:layout_marginEnd="@dimen/dp8"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="16sp"
android:layout_marginTop="@dimen/dp8"
android:text="@string/recovered"/>
<TextView
android:id="@+id/tv_recovered_globe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginBottom="@dimen/dp8"
android:text="-"/>
</LinearLayout>
<!-- Endregion-->
<!-- Region text deaths-->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="16sp"
android:layout_marginTop="10dp"
android:text="@string/deaths"/>
<TextView
android:id="@+id/tv_deaths_globe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginBottom="@dimen/dp8"
android:text="-"/>
</LinearLayout>
<!-- Endregion-->
</LinearLayout>
<LinearLayout
android:id="@+id/lay_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/lay_globe"
android:layout_marginStart="@dimen/dp16"
android:layout_marginEnd="@dimen/dp16"
android:orientation="horizontal">
<TextView
style="@style/TextContentMainActivity"
android:layout_marginTop="@dimen/dp8"
android:layout_weight="4"
android:text="@string/countries"/>
<TextView
style="@style/TextContentMainActivity"
android:layout_marginTop="@dimen/dp8"
android:layout_weight="5"
android:text="@string/total_cases"/>
<TextView
style="@style/TextContentMainActivity"
android:layout_marginTop="@dimen/dp8"
android:layout_weight="5"
android:text="@string/recovered"/>
<TextView
style="@style/TextContentMainActivity"
android:layout_marginTop="@dimen/dp8"
android:layout_weight="5"
android:text="@string/deaths"/>
</LinearLayout>
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminate="true"/>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/lay_header"
android:layout_marginTop="@dimen/dp8"
android:layout_marginBottom="@dimen/dp8">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_country"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:listitem="@layout/list_country"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</RelativeLayout>
Dan tambahkan kode berikut, setelah itu buka lah activity_chart_country.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/dp16"
android:layout_weight="1"
android:background="@drawable/bg_header_gray"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
tools:ignore="NestedWeight">
<ImageView
android:id="@+id/img_flag_chart"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/dp8"
android:layout_weight="1"
android:src="@drawable/ic_launcher_background"
tools:ignore="NestedWeight" />
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/dp8"
android:layout_weight="1"
app:cardCornerRadius="@dimen/dp8"
app:cardElevation="@dimen/dp4">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/tv_country_chart"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/countries"
android:textColor="@color/colorPrimaryDark"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_curent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/currently"
android:textAlignment="center"
android:textSize="12sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
tools:ignore="NestedWeight">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/dp8"
android:layout_weight="1"
app:cardCornerRadius="@dimen/dp8"
app:cardElevation="@dimen/dp4">
<LinearLayout
style="@style/LinearLayoutForCardView"
android:background="@color/orange">
<TextView
style="@style/TitleInsideCardViewInChart"
android:text="@string/total_confirmed"
android:textColor="@android:color/white" />
<TextView
android:id="@+id/tv_total_confirmed_current"
style="@style/ContentTextInsideCardViewChart"
android:text="@string/currently"
android:textColor="@android:color/white" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/dp8"
android:layout_weight="1"
app:cardCornerRadius="@dimen/dp8"
app:cardElevation="@dimen/dp4">
<LinearLayout
style="@style/LinearLayoutForCardView"
android:background="@color/orange_grey">
<TextView
style="@style/TitleInsideCardViewInChart"
android:text="@string/new_confirmed"
android:textColor="@android:color/white" />
<TextView
android:id="@+id/tv_new_confirmed_current"
style="@style/ContentTextInsideCardViewChart"
android:text="@string/currently"
android:textColor="@android:color/white" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
tools:ignore="NestedWeight">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/dp8"
android:layout_weight="1"
app:cardCornerRadius="@dimen/dp8"
app:cardElevation="@dimen/dp4">
<LinearLayout
style="@style/LinearLayoutForCardView"
android:background="@color/yellow">
<TextView
style="@style/TitleInsideCardViewInChart"
android:text="@string/total_deaths"
android:textColor="@android:color/holo_red_light" />
<TextView
android:id="@+id/tv_total_deaths_current"
style="@style/ContentTextInsideCardViewChart"
android:text="@string/currently"
android:textColor="@android:color/holo_red_light" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/dp8"
android:layout_weight="1"
app:cardCornerRadius="@dimen/dp8"
app:cardElevation="@dimen/dp4">
<LinearLayout
style="@style/LinearLayoutForCardView"
android:background="@color/yellow_grey">
<TextView
style="@style/TitleInsideCardViewInChart"
android:text="@string/new_deaths"
android:textColor="@android:color/holo_red_light" />
<TextView
android:id="@+id/tv_new_deaths_current"
style="@style/ContentTextInsideCardViewChart"
android:text="@string/currently"
android:textColor="@android:color/holo_red_light" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
tools:ignore="NestedWeight">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/dp8"
android:layout_weight="1"
app:cardCornerRadius="@dimen/dp8"
app:cardElevation="@dimen/dp4">
<LinearLayout
style="@style/LinearLayoutForCardView"
android:background="@color/colorAccent">
<TextView
style="@style/TitleInsideCardViewInChart"
android:text="@string/total_recoverd"
android:textColor="@android:color/black" />
<TextView
android:id="@+id/tv_total_recovered_current"
style="@style/ContentTextInsideCardViewChart"
android:text="@string/currently"
android:textColor="@android:color/holo_red_light" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/dp8"
android:layout_weight="1"
app:cardCornerRadius="@dimen/dp8"
app:cardElevation="@dimen/dp4">
<LinearLayout
style="@style/LinearLayoutForCardView"
android:background="@color/blue_grey">
<TextView
style="@style/TitleInsideCardViewInChart"
android:text="@string/new_recovered"
android:textColor="@android:color/black"/>
<TextView
android:id="@+id/tv_new_recovered_current"
style="@style/ContentTextInsideCardViewChart"
android:text="@string/currently"
android:textColor="@android:color/holo_red_light" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/dp4"
android:orientation="horizontal"
android:layout_weight="1">
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/chart_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</LinearLayout>
Tambah kan kode berikut pada activity_chart_country.xml. Lalu buat lah layout baru dan beri nama list_country.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@android:color/white"
android:orientation="vertical">
<LinearLayout
android:id="@+id/lay_globe_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/dp8"
android:layout_margin="@dimen/dp8"
android:background="@drawable/bg_header_gray"
android:orientation="horizontal">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/img_flag_country"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginStart="@dimen/dp4"
android:src="@mipmap/ic_launcher_round"/>
<TextView
android:id="@+id/tv_country_name"
style="@style/TextContentListCountry"
android:layout_weight="4"
android:textStyle="bold"
android:text="@string/countries"/>
<TextView
android:id="@+id/tv_country_total_case"
style="@style/TextContentListCountry"
android:layout_weight="5"
android:text="@string/total_cases"/>
<TextView
android:id="@+id/tv_country_total_recovered"
style="@style/TextContentListCountry"
android:layout_weight="5"
android:text="@string/recovered"/>
<TextView
android:id="@+id/tv_country_total_deaths"
style="@style/TextContentListCountry"
android:layout_weight="5"
android:text="@string/deaths"/>
</LinearLayout>
</LinearLayout>
Dan tambahkan kode berikut. Tambahkan juga values color, string, dan style
colors.xml
<color name="orange">#FF5722</color>
<color name="yellow">#FFEB3B</color>
<color name="red">#B71C1C</color>
<color name="orange_grey">#FF9E80</color>
<color name="yellow_grey">#FFFF8D</color>
<color name="blue_grey">#84FFFF</color>
strings.xml
<string name="confirmed">Confirmed</string>
<string name="deaths">Deaths</string>
<string name="recovered">Recovered</string>
<string name="countries">Countries</string>
<string name="total_cases">Total cases</string>
<string name="nama_negara">Country Name</string>
<string name="currently">Currently</string>
<string name="total_confirmed">Total Confirmed</string>
<string name="new_confirmed">New Confirmed</string>
<string name="total_deaths">Total Deaths</string>
<string name="total_recoverd">Total Recoverd</string>
<string name="new_deaths">New Deaths</string>
<string name="new_recovered">New Recoverd</string>
styles.xml
<style name="LinearLayoutForCardView">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:gravity">center</item>
<item name="android:orientation">vertical</item>
</style>
<style name="TitleInsideCardViewInChart">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textAlignment">center</item>
<item name="android:textSize">12sp</item>
<item name="android:textStyle">bold</item>
</style>
<style name="ContentTextInsideCardViewChart">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textAlignment">center</item>
<item name="android:textSize">20sp</item>
<item name="android:textStyle">bold</item>
</style>
<style name="TextContentListCountry">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">@android:color/black</item>
<item name="android:layout_gravity">center_horizontal</item>
<item name="android:textSize">12sp</item>
</style>
<style name="TextContentMainActivity">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">@android:color/black</item>
<item name="android:textStyle">bold</item>
<item name="android:textSize">12sp</item>
</style>
Dan buat layout baru dengan nama dimens.xml dan letakan didalam package values. dan tambakan kode yg sudah diberikan
dimens.xml
<dimen name="dp2">2dp</dimen>
<dimen name="dp8">8dp</dimen>
<dimen name="dp6">6dp</dimen>
<dimen name="dp16">16dp</dimen>
<dimen name="dp4">4dp</dimen>
lalu buka package drawable dan buat layout bg_blue.xml, bg_header_gray.xml, dan box_search_country.xml. Dan tambah kan kode yg sudah diberikan
bg_blue.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/colorPrimaryDark"/>
<corners android:radius="@dimen/dp6"/>
</shape>
bg_header.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#E4E4E4"/>
</shape>
box_search_country.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:color="@color/colorPrimary"
android:width="@dimen/dp2"/>
<corners android:radius="8dp"/>
</shape>
Tambahkan vector swap vert pada package drawable dan beri nama sequence
Coding
Buat lah object pada package network dan beri nama ApiClient, dan tambahkan kode berikut
fun getClient(): ApiService {
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.BODY
val httpClient = OkHttpClient.Builder()
httpClient.addInterceptor(logging)
val retrofit = Retrofit.Builder()
.baseUrl("https://api.covid19api.com/")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build()
return retrofit.create(ApiService::class.java)
}
Fungsi ApiClient adalah kita mensetting retrofit agar dapat digunakan untuk mendapatkan data dari database. Kemudian buatlah Interface pada package network, beri nama ApiService
@GET("summary")
fun getAllCountry(): Call<AllCountries>
@GET("dayone/country/{country}")
fun getInfoService(@Path("country") dataCovid: String): Call<List<InfoCountry>>
Fungsi ApiService adalah sebagai endpoint. Retrofit membutuhkan POJO guna akses transaksi ke dalam struktur dari JSON, buatlah file Model.kt pada package model, dan tambahkan kode berikut
data class AllCountries (val Global: World, val Countries: ArrayList<Countries>)
data class World (
val TotalConfirmed: String = "",
val TotalDeaths: String = "",
val TotalRecovered: String = ""
)
data class Countries(
val Country: String = "",
val CountryCode: String = "",
val Slug: String = "",
val NewConfirmed: String = "",
val NewDeaths: String = "",
val TotalDeaths: String = "",
val NewRecovered: String = "",
val TotalRecovered: String = "",
val TotalConfirmed: String = "",
val Date: String = ""
)
data class InfoCountry(
val Confirmed: String = "",
val Recovered: String = "",
val Deaths: String = "",
val Active: String = "",
val Date: String = ""
)
Setelah kita mensetting semua data yg dibutuh kan untuk didapat kan mari kita buat class adapter pada package, beri nama CountryAdapter dan tambahkan kode berikut dalam class adapter
class CountryAdapter(val country: ArrayList<Countries>, val clickListener: (Countries) -> Unit):
RecyclerView.Adapter<CountryAdapter.CountryViewHolder>(), Filterable {
var countryFilterList = ArrayList<Countries>()
init {
countryFilterList = country
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CountryViewHolder {
return CountryViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.list_country, parent, false))
}
override fun getItemCount(): Int = countryFilterList.size
override fun onBindViewHolder(holder: CountryViewHolder, position: Int) {
holder.bindItem(countryFilterList[position], clickListener)
}
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
var charSearch = constraint.toString()
countryFilterList = if (charSearch.isEmpty()) {
country
} else {
val resultList = ArrayList<Countries>()
for (row in country) {
if (row.Country.toLowerCase(Locale.ROOT).contains(charSearch.toLowerCase(Locale.ROOT))) {
resultList.add(row)
}
}
resultList
}
val filterResult = FilterResults()
filterResult.values = countryFilterList
return filterResult
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
countryFilterList = results?.values as ArrayList<Countries>
notifyDataSetChanged()
}
}
}
class CountryViewHolder(view: View):RecyclerView.ViewHolder(view) {
val tvCountry = itemView.findViewById<TextView>(R.id.tv_country_name)
val tvTotalCase = itemView.findViewById<TextView>(R.id.tv_country_total_case)
val tvTotalRecoverd = itemView.findViewById<TextView>(R.id.tv_country_total_recovered)
val tvTotalDeath = itemView.findViewById<TextView>(R.id.tv_country_total_deaths)
val imgFlag = itemView.findViewById<ImageView>(R.id.img_flag_country)
fun bindItem(countries: Countries, clickListener: (Countries) -> Unit) {
tvCountry.text = countries.Country
val formatter: NumberFormat = DecimalFormat("#,###")
tvTotalCase.text = formatter.format(countries.TotalConfirmed.toDouble())
tvTotalRecoverd.text = formatter.format(countries.TotalRecovered.toDouble())
tvTotalDeath.text = formatter.format(countries.TotalRecovered.toDouble())
Glide.with(itemView.context).load("https://www.countryflags.io/" + countries.CountryCode + "/flat/16.png").into(imgFlag)
itemView.setOnClickListener {
clickListener(countries)
}
}
}
}
Setelah kita mensetting adapter nya kita pindah ke MainActivity, karena kita mengunakan patern MVP buat lah class MainPresenter dan Interface lalu beri nama MainService. Tambahkan kode berikut pada interface MainService
fun sequenceListener(ascending: Boolean)
fun itemCliked(country: Countries)
fun hideProgressBar()
fun showCountry(listCountries: ArrayList<Countries>)
fun showWorld(dataCovid: World)
Dan tambah kan kode berikut pada MainPresenter untuk mendapat kan data dari database
class MainPresenter(private val view: MainService) {
fun getCountry() {
val apiService = ApiClient.getClient()
apiService.getAllCountry().enqueue(object : Callback<AllCountries> {
override fun onResponse(call: Call<AllCountries>, response: Response<AllCountries>) {
view.hideProgressBar()
if (response.body() != null) {
response.body()!!.Global.let { view.showWorld(it) }
response.body()!!.Countries.let { view.showCountry(it) }
} else {
view.hideProgressBar()
}
}
override fun onFailure(call: Call<AllCountries>, t: Throwable) {
t.message
}
})
}
}
Beri akses kepada MainService aagar bisa digunakan didalam MainActivity. Caranya adalah menambahkan kode berikut. Tambah kan kode berikut untuk menampil kan data didalam class MainActivity
class MainActivity : AppCompatActivity(), MainService {
Dengan itu kita bisa mengimplementasi kan fungsi di dalama MainService
private val mainPresenter = MainPresenter(this)
private lateinit var countryAdapter: CountryAdapter
private var ascending = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mainPresenter.getCountry()
btn_sequence.setOnClickListener {
sequenceListener(ascending)
ascending = !ascending
}
search_view.setOnQueryTextListener(object : androidx.appcompat.widget.SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
countryAdapter.filter.filter(newText)
return false
}
})
swipe_refresh.setOnRefreshListener {
mainPresenter.getCountry()
swipe_refresh.isRefreshing = false
}
}
override fun sequenceListener(ascending: Boolean) {
rv_country.apply {
layoutManager = LinearLayoutManager(this@MainActivity)
setHasFixedSize(true)
if (ascending) {
(layoutManager as LinearLayoutManager).reverseLayout = true
(layoutManager as LinearLayoutManager).stackFromEnd = true
Toast.makeText(this@MainActivity, "Z-A", Toast.LENGTH_SHORT).show()
} else {
(layoutManager as LinearLayoutManager).reverseLayout = true
(layoutManager as LinearLayoutManager).stackFromEnd = true
Toast.makeText(this@MainActivity, "A-Z", Toast.LENGTH_SHORT).show()
}
adapter = countryAdapter
}
}
override fun itemCliked(country: Countries) {
val intent = Intent(this, ChartCountryActivity::class.java)
intent.putExtra(ChartCountryActivity.EXTRA_COUNTRY, country.Country)
intent.putExtra(ChartCountryActivity.EXTRA_LASTEST_UPDATE, country.Date)
intent.putExtra(ChartCountryActivity.EXTRA_NEW_DEATH, country.NewDeaths)
intent.putExtra(ChartCountryActivity.EXTRA_NEW_CONFIRMED, country.NewConfirmed)
intent.putExtra(ChartCountryActivity.EXTRA_NEW_RECOVERED, country.NewRecovered)
intent.putExtra(ChartCountryActivity.EXTRA_TOTAL_CONFIRMED, country.TotalConfirmed)
intent.putExtra(ChartCountryActivity.EXTRA_TOTAL_DEATH, country.TotalDeaths)
intent.putExtra(ChartCountryActivity.EXTRA_TOTAL_RECOVERED, country.TotalRecovered)
intent.putExtra(ChartCountryActivity.EXTRA_COUNTRY_CODE, country.CountryCode)
startActivity(intent)
}
override fun hideProgressBar() {
progress_bar.visibility = View.GONE
}
override fun showCountry(listCountries: ArrayList<Countries>) {
rv_country.apply {
layoutManager = LinearLayoutManager(this@MainActivity)
setHasFixedSize(true)
countryAdapter = CountryAdapter(listCountries) {
itemCliked(it)
}
adapter = countryAdapter
}
}
override fun showWorld(dataCovid: World) {
val formatter: NumberFormat = DecimalFormat("#,##")
tv_confirmed_globe.text = formatter.format(dataCovid.TotalConfirmed.toDouble())
tv_deaths_globe.text = formatter.format(dataCovid.TotalDeaths.toDouble())
tv_recovered_globe.text = formatter.format(dataCovid.TotalRecovered.toDouble())
}
Setelah itu kita pindah ke ChartCountryActivity sekali lagi karena kita menggunakan MVP tambahkan class ChartCountryPresenter dan Interface ChartCountryService. Tambahkan function showCountry dan loadImage pada ChartCountryService
fun showCountry(dataCovid: List<InfoCountry>)
fun loadImage()
Lalu tambahkan kode berikut untuk mendapat kan setiap negara
class ChartCountryPresenter(val view: ChartCountryService) {
fun getCountry(dataCountry: String) {
val apiService = ApiClient.getClient()
apiService.getInfoService(dataCountry).enqueue(object : Callback<List<InfoCountry>> {
override fun onResponse(call: Call<List<InfoCountry>>, response: Response<List<InfoCountry>>) {
if (response.body() != null) {
response.body()!!.let { view.showCountry(it) }
}
}
override fun onFailure(call: Call<List<InfoCountry>>, t: Throwable) {
t.message
}
})
}
}
Lalu tambahkan kode berikut untuk menampilkan data yg sudah kita ambil dari ChartCountryAdapter
class ChartCountryActivity : AppCompatActivity(), ChartCountryService {
private lateinit var sharedPreferences: SharedPreferences
private var sharedPrefFile = "kotlinsharedpreferences"
private var dayCases = ArrayList<String>()
private val chartCountryPresenter = ChartCountryPresenter(this)
private lateinit var dataFlag: String
private lateinit var dataCountry: String
companion object {
const val EXTRA_COUNTRY = "country"
const val EXTRA_LASTEST_UPDATE = "date"
const val EXTRA_NEW_DEATH = "new_death"
const val EXTRA_NEW_CONFIRMED = "new_confirmed"
const val EXTRA_NEW_RECOVERED = "new_recovered"
const val EXTRA_TOTAL_CONFIRMED = "total_confirmed"
const val EXTRA_TOTAL_DEATH = "total_death"
const val EXTRA_TOTAL_RECOVERED = "total_recovered"
const val EXTRA_COUNTRY_CODE = "code"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chart_country)
sharedPreferences = this.getSharedPreferences(sharedPrefFile, Context.MODE_PRIVATE)
val country = intent.getStringExtra(EXTRA_COUNTRY)
val date = intent.getStringExtra(EXTRA_LASTEST_UPDATE)
val newDeath = intent.getStringExtra(EXTRA_NEW_DEATH)
val newConfirmed = intent.getStringExtra(EXTRA_NEW_CONFIRMED)
val newReovered = intent.getStringExtra(EXTRA_NEW_RECOVERED)
val totalConfirmed = intent.getStringExtra(EXTRA_TOTAL_CONFIRMED)
val totalDeath = intent.getStringExtra(EXTRA_TOTAL_DEATH)
val totalRecovered = intent.getStringExtra(EXTRA_TOTAL_RECOVERED)
val countryCode = intent.getStringExtra(EXTRA_COUNTRY_CODE)
val formatter: NumberFormat = DecimalFormat("#,###")
tv_country_chart.text = country
tv_curent.text = date
tv_total_confirmed_current.text = formatter.format(totalConfirmed.toDouble())
tv_new_confirmed_current.text = formatter.format(newConfirmed.toDouble())
tv_total_recovered_current.text = formatter.format(totalRecovered.toDouble())
tv_new_recovered_current.text = formatter.format(newReovered.toDouble())
tv_total_deaths_current.text = formatter.format(totalDeath.toDouble())
tv_new_deaths_current.text = formatter.format(newDeath.toDouble())
val editor: SharedPreferences.Editor = sharedPreferences.edit()
editor.putString(country, country)
editor.apply()
editor.commit()
val saveDataCountry = sharedPreferences.getString(country, country)
val saveCountryFlag = sharedPreferences.getString(countryCode, countryCode)
dataCountry = saveDataCountry.toString()
dataFlag = saveCountryFlag.toString() + "/flat/64.png"
chartCountryPresenter.getCountry(dataCountry)
if (saveCountryFlag != null) {
loadImage()
} else {
Toast.makeText(this, "Image not found", Toast.LENGTH_SHORT).show()
}
}
override fun showCountry(dataCovid: List<InfoCountry>) {
val barEntries1: ArrayList<BarEntry> = ArrayList()
val barEntries2: ArrayList<BarEntry> = ArrayList()
val barEntries3: ArrayList<BarEntry> = ArrayList()
val barEntries4: ArrayList<BarEntry> = ArrayList()
var i = 0
while (i < dataCovid.size ?: 0) {
for (s in dataCovid) {
val barEntry1 = BarEntry(i.toFloat(), s.Confirmed.toFloat())
val barEntry2 = BarEntry(i.toFloat(), s.Deaths.toFloat())
val barEntry3 = BarEntry(i.toFloat(), s.Recovered.toFloat())
val barEntry4 = BarEntry(i.toFloat(), s.Active.toFloat())
val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:SS'Z'")
val outputFormat = SimpleDateFormat("dd-MM-yyyy")
val date: Date? = inputFormat.parse(s.Date)
val formattedDate: String = outputFormat.format(date!!)
dayCases.add(formattedDate)
barEntries1.add(barEntry1)
barEntries2.add(barEntry2)
barEntries3.add(barEntry3)
barEntries4.add(barEntry4)
i++
}
}
val xAxis: XAxis = chart_view.xAxis
xAxis.valueFormatter = IndexAxisValueFormatter(dayCases)
chart_view.axisLeft.axisMinimum = 0f
xAxis.position = XAxis.XAxisPosition.BOTTOM
xAxis.granularity = 1f
xAxis.setCenterAxisLabels(true)
xAxis.isGranularityEnabled = true
val barDataSet1 = BarDataSet(barEntries1, "Confirmed")
val barDataSet2 = BarDataSet(barEntries2, "Deaths")
val barDataSet3 = BarDataSet(barEntries3, "Recovered")
val barDataSet4 = BarDataSet(barEntries4, "Active")
barDataSet1.setColor(Color.parseColor("#F44336"))
barDataSet2.setColor(Color.parseColor("#FFEB3B"))
barDataSet3.setColor(Color.parseColor("#03DAC5"))
barDataSet4.setColor(Color.parseColor("#2196F3"))
val data = BarData(barDataSet1, barDataSet2, barDataSet3, barDataSet4)
chart_view.data = data
val barSpace = 0.02f
val groupSpace = 0.3f
val groupCount = 4f
data.barWidth = 0.15f
chart_view.invalidate()
chart_view.setNoDataTextColor(android.R.color.black)
chart_view.setTouchEnabled(true)
chart_view.description.isEnabled = false
chart_view.xAxis.axisMinimum = 0f
chart_view.setVisibleXRangeMaximum(0f + chart_view.barData.getGroupWidth(groupSpace, barSpace) * groupCount)
chart_view.groupBars(0f, groupSpace, barSpace)
}
override fun loadImage() {
Glide.with(this).load("https://www.countryflags.io/$dataFlag").into(img_flag_chart)
}
}
Dan tambahkan kode berikut supaya kita bisa mengakses internet
<uses-permission android:name="android.permission.INTERNET"/>
Begitulah cara membuat aplikasi Covid-19