Skip to content

Commit 08b95ba

Browse files
committed
add favorite user button
1 parent 9520878 commit 08b95ba

11 files changed

Lines changed: 169 additions & 2 deletions

File tree

app/build.gradle

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
plugins {
22
id 'com.android.application'
33
id 'org.jetbrains.kotlin.android'
4+
id 'kotlin-kapt'
45
}
56

67
android {
@@ -47,6 +48,15 @@ dependencies {
4748
implementation 'com.github.bumptech.glide:glide:4.12.0'
4849
implementation 'de.hdodenhof:circleimageview:3.1.0'
4950
implementation "androidx.viewpager2:viewpager2:1.0.0"
51+
def room_version = '2.5.1'
52+
implementation "androidx.room:room-runtime:$room_version"
53+
annotationProcessor "androidx.room:room-compiler:$room_version"
54+
androidTestImplementation "androidx.room:room-testing:$room_version"
55+
implementation "androidx.room:room-ktx:$room_version"
56+
kapt "androidx.room:room-compiler:$room_version"
57+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
58+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
59+
5060
testImplementation 'junit:junit:4.13.2'
5161
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
5262
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.riyandifirman.githubuser.favorite
2+
3+
import androidx.room.Entity
4+
import androidx.room.PrimaryKey
5+
6+
@Entity(tableName = "favorite_user")
7+
data class FavoriteUser(
8+
val login : String,
9+
@PrimaryKey
10+
val id : Int
11+
) : java.io.Serializable
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.riyandifirman.githubuser.favorite
2+
3+
import androidx.lifecycle.LiveData
4+
import androidx.room.Dao
5+
import androidx.room.Insert
6+
import androidx.room.Query
7+
import com.riyandifirman.githubuser.favorite.FavoriteUser
8+
9+
@Dao
10+
interface FavoriteUserDao {
11+
@Insert
12+
suspend fun insertFavoriteUser(favoriteUser: FavoriteUser)
13+
14+
@Query("SELECT * FROM favorite_user")
15+
fun getFavoriteUser(): LiveData<List<FavoriteUser>>
16+
17+
@Query("SELECT count(*) FROM favorite_user WHERE favorite_user.id = :id")
18+
suspend fun isFavorite(id: Int): Int
19+
20+
@Query("DELETE FROM favorite_user WHERE favorite_user.id = :id")
21+
suspend fun deleteFavoriteUser(id: Int): Int
22+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.riyandifirman.githubuser.favorite
2+
3+
import android.content.Context
4+
import androidx.room.Database
5+
import androidx.room.Room
6+
import androidx.room.RoomDatabase
7+
8+
@Database(entities = [FavoriteUser::class], version = 1)
9+
10+
abstract class UserDatabase: RoomDatabase() {
11+
abstract fun favoriteUserDao(): FavoriteUserDao
12+
13+
companion object{
14+
var INSTANCE: UserDatabase? = null
15+
16+
fun getInstance(context: Context): UserDatabase? {
17+
if (INSTANCE == null) {
18+
synchronized(UserDatabase::class) {
19+
INSTANCE = Room.databaseBuilder(context.applicationContext,
20+
UserDatabase::class.java, "favorite_user.db")
21+
.build()
22+
}
23+
}
24+
return INSTANCE
25+
}
26+
}
27+
}

app/src/main/java/com/riyandifirman/githubuser/ui/detail/DetailUserActivity.kt

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@ import android.view.View
66
import androidx.lifecycle.ViewModelProvider
77
import androidx.viewpager.widget.ViewPager
88
import com.bumptech.glide.Glide
9+
import com.riyandifirman.githubuser.R
910
import com.riyandifirman.githubuser.adapter.SectionsPagerAdapter
1011
import com.riyandifirman.githubuser.databinding.ActivityDetailUserBinding
1112
import com.riyandifirman.githubuser.viewmodel.DetailUserViewModel
13+
import kotlinx.coroutines.CoroutineScope
14+
import kotlinx.coroutines.Dispatchers
15+
import kotlinx.coroutines.launch
16+
import kotlinx.coroutines.withContext
1217

1318
class DetailUserActivity : AppCompatActivity() {
1419

@@ -18,6 +23,7 @@ class DetailUserActivity : AppCompatActivity() {
1823
// companion object digunakan untuk membuat variabel yang dapat diakses dari mana saja
1924
companion object {
2025
const val EXTRA_USERNAME = "extra_username"
26+
const val EXTRA_ID = "extra_id"
2127
}
2228

2329
override fun onCreate(savedInstanceState: Bundle?) {
@@ -27,13 +33,14 @@ class DetailUserActivity : AppCompatActivity() {
2733

2834
// mengambil data dari intent yang dikirimkan dari MainActivity
2935
val username = intent.getStringExtra(EXTRA_USERNAME)
36+
val id = intent.getIntExtra(EXTRA_ID, 0)
3037

3138
// membuat bundle untuk mengirimkan data ke fragment
3239
val bundle = Bundle()
3340
bundle.putString(EXTRA_USERNAME, username)
3441

3542
// menginisialisasi viewModel
36-
viewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(DetailUserViewModel::class.java)
43+
viewModel = ViewModelProvider(this).get(DetailUserViewModel::class.java)
3744

3845
if (username != null) {
3946
viewModel.setDetailUser(username)
@@ -56,6 +63,34 @@ class DetailUserActivity : AppCompatActivity() {
5663
}
5764
}
5865

66+
var isCheck = false
67+
CoroutineScope(Dispatchers.IO).launch {
68+
val count = viewModel.isFavorite(id)
69+
withContext(Dispatchers.Main) {
70+
if (count != null) {
71+
if (count > 0) {
72+
isCheck = true
73+
binding.toggle.isChecked = true
74+
} else {
75+
isCheck = false
76+
binding.toggle.isChecked = false
77+
}
78+
}
79+
}
80+
}
81+
82+
binding.toggle.setOnClickListener{
83+
isCheck = !isCheck
84+
if (isCheck) {
85+
if (username != null) {
86+
viewModel.insertFavoriteUser(username, id)
87+
}
88+
} else {
89+
viewModel.deleteFavoriteUser(id)
90+
}
91+
binding.toggle.isChecked = isCheck
92+
}
93+
5994
// menginisialisasi adapter untuk view pager
6095
val sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager, bundle)
6196
val viewPager: ViewPager = binding.viewPager

app/src/main/java/com/riyandifirman/githubuser/ui/main/MainActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class MainActivity : AppCompatActivity() {
3838
// panggil DetailUserActivity dengan membawa data user
3939
val intent = Intent(this@MainActivity, DetailUserActivity::class.java)
4040
intent.putExtra(DetailUserActivity.EXTRA_USERNAME, data.login)
41+
intent.putExtra(DetailUserActivity.EXTRA_ID, data.id)
4142
startActivity(intent)
4243
}
4344
})

app/src/main/java/com/riyandifirman/githubuser/viewmodel/DetailUserViewModel.kt

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,35 @@
11
package com.riyandifirman.githubuser.viewmodel
22

3+
import android.app.Application
34
import android.util.Log
5+
import androidx.lifecycle.AndroidViewModel
46
import androidx.lifecycle.LiveData
57
import androidx.lifecycle.MutableLiveData
68
import androidx.lifecycle.ViewModel
79
import com.riyandifirman.githubuser.ApiConfig
10+
import com.riyandifirman.githubuser.favorite.FavoriteUser
11+
import com.riyandifirman.githubuser.favorite.FavoriteUserDao
12+
import com.riyandifirman.githubuser.favorite.UserDatabase
813
import com.riyandifirman.githubuser.response.DetailUserResponse
14+
import kotlinx.coroutines.CoroutineScope
15+
import kotlinx.coroutines.Dispatchers
16+
import kotlinx.coroutines.launch
917
import retrofit2.Call
1018
import retrofit2.Callback
1119
import retrofit2.Response
1220

13-
class DetailUserViewModel : ViewModel() {
21+
class DetailUserViewModel(application: Application) : AndroidViewModel(application) {
1422
val _user = MutableLiveData<DetailUserResponse>()
1523
val user: LiveData<DetailUserResponse> = _user
1624

25+
private var userDao: FavoriteUserDao?
26+
private var userDatabase: UserDatabase?
27+
28+
init {
29+
userDatabase = UserDatabase.getInstance(application)
30+
userDao = userDatabase?.favoriteUserDao()
31+
}
32+
1733
// fungsi untuk mengambil data dari API
1834
fun setDetailUser(username: String) {
1935
// memanggil fungsi getDetailUser pada ApiConfig untuk mengambil data dengan parameter username
@@ -39,4 +55,22 @@ class DetailUserViewModel : ViewModel() {
3955

4056
// fungsi untuk mengembalikan data
4157
fun getDetailUser(): LiveData<DetailUserResponse> = user
58+
59+
// fungsi untuk menambahkan data user favorit ke dalam database
60+
fun insertFavoriteUser(username: String, id: Int) {
61+
CoroutineScope(Dispatchers.IO).launch {
62+
var user = FavoriteUser(username, id)
63+
userDao?.insertFavoriteUser(user)
64+
}
65+
}
66+
67+
// fungsi untuk mengecek apakah user sudah ada di database atau belum
68+
suspend fun isFavorite(id: Int) = userDao?.isFavorite(id)
69+
70+
// fungsi untuk menghapus data user favorit dari database
71+
fun deleteFavoriteUser(id: Int) {
72+
CoroutineScope(Dispatchers.IO).launch {
73+
userDao?.deleteFavoriteUser(id)
74+
}
75+
}
4276
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<selector xmlns:android="http://schemas.android.com/apk/res/android">
3+
<item android:drawable="@drawable/ic_baseline_unfavorite_24" android:state_checked="false" />
4+
<item android:drawable="@drawable/ic_baseline_favorite_24" android:state_checked="true" />
5+
</selector>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<vector android:height="24dp" android:tint="#6200EE"
2+
android:viewportHeight="24" android:viewportWidth="24"
3+
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
4+
<path android:fillColor="@android:color/white" android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/>
5+
</vector>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<vector android:height="24dp" android:tint="#828282"
2+
android:viewportHeight="24" android:viewportWidth="24"
3+
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
4+
<path android:fillColor="@android:color/white" android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/>
5+
</vector>

0 commit comments

Comments
 (0)