Skip to content

Commit 6b2c7d9

Browse files
Merge pull request #20 from reactivedroid/feature/clean-arch
More towards clean code architecture
2 parents 671f82c + 5c25ce3 commit 6b2c7d9

22 files changed

+242
-119
lines changed

app/src/main/java/com/android/tvflix/TvFlixApplication.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.android.tvflix
22

33
import android.app.Application
44
import com.android.tvflix.config.AppConfig
5+
import com.google.firebase.FirebaseApp
56
import dagger.hilt.android.HiltAndroidApp
67
import timber.log.Timber
78
import javax.inject.Inject
@@ -13,6 +14,7 @@ class TvFlixApplication : Application() {
1314

1415
override fun onCreate() {
1516
super.onCreate()
17+
FirebaseApp.initializeApp(this)
1618
if (BuildConfig.DEBUG) {
1719
Timber.plant(Timber.DebugTree())
1820
}

app/src/main/java/com/android/tvflix/db/TvFlixDatabase.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import androidx.room.RoomDatabase
55
import com.android.tvflix.db.favouriteshow.FavoriteShow
66
import com.android.tvflix.db.favouriteshow.ShowDao
77

8-
@Database(entities = [FavoriteShow::class], version = 2, exportSchema = false)
8+
@Database(entities = [FavoriteShow::class], version = 3, exportSchema = false)
99
abstract class TvFlixDatabase : RoomDatabase() {
1010

1111
abstract fun showDao(): ShowDao

app/src/main/java/com/android/tvflix/db/favouriteshow/FavoriteShow.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ data class FavoriteShow(
1212
val imageUrl: String?,
1313
var summary: String?,
1414
var rating: String?,
15-
var runtime: Int?,
16-
val isFavorite: Boolean
15+
var runtime: Int?
1716
)
1817

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.android.tvflix.domain
2+
3+
import com.android.tvflix.db.favouriteshow.FavoriteShow
4+
import com.android.tvflix.di.IoDispatcher
5+
import com.android.tvflix.favorite.FavoriteShowsRepository
6+
import kotlinx.coroutines.CoroutineDispatcher
7+
import javax.inject.Inject
8+
9+
class AddToFavoritesUseCase @Inject
10+
constructor(
11+
private val favoriteShowsRepository: FavoriteShowsRepository,
12+
@IoDispatcher ioDispatcher: CoroutineDispatcher
13+
) : SuspendUseCase<FavoriteShow, Unit>(ioDispatcher) {
14+
override suspend fun execute(parameters: FavoriteShow) {
15+
favoriteShowsRepository.insertIntoFavorites(parameters)
16+
}
17+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.android.tvflix.domain
2+
3+
import com.android.tvflix.db.favouriteshow.FavoriteShow
4+
import com.android.tvflix.di.IoDispatcher
5+
import com.android.tvflix.favorite.FavoriteShowsRepository
6+
import com.android.tvflix.home.HomeViewModel
7+
import kotlinx.coroutines.CoroutineDispatcher
8+
import java.text.SimpleDateFormat
9+
import java.util.*
10+
import javax.inject.Inject
11+
12+
class GetFavoriteShowsUseCase
13+
@Inject
14+
constructor(
15+
private val favoriteShowsRepository: FavoriteShowsRepository,
16+
@IoDispatcher ioDispatcher: CoroutineDispatcher
17+
) : SuspendUseCase<Unit, List<Long>>(ioDispatcher) {
18+
override suspend fun execute(parameters: Unit): List<Long> {
19+
return favoriteShowsRepository.allFavoriteShowIds()
20+
}
21+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.android.tvflix.domain
2+
3+
import com.android.tvflix.di.IoDispatcher
4+
import com.android.tvflix.model.respositores.SchedulesRepository
5+
import com.android.tvflix.network.home.Episode
6+
import kotlinx.coroutines.CoroutineDispatcher
7+
import java.text.SimpleDateFormat
8+
import java.util.*
9+
import javax.inject.Inject
10+
11+
12+
class GetSchedulesUseCase
13+
@Inject
14+
constructor(
15+
private val schedulesRepository: SchedulesRepository,
16+
@IoDispatcher ioDispatcher: CoroutineDispatcher
17+
) :
18+
SuspendUseCase<Unit, List<Episode>>(ioDispatcher) {
19+
override suspend fun execute(parameters: Unit): List<Episode> {
20+
return schedulesRepository.getSchedule(country = COUNTRY, currentDate = currentDate)
21+
}
22+
23+
companion object {
24+
private const val QUERY_DATE_FORMAT = "yyyy-MM-dd"
25+
const val COUNTRY = "US"
26+
private val currentDate: String
27+
get() {
28+
val simpleDateFormat = SimpleDateFormat(QUERY_DATE_FORMAT, Locale.US)
29+
val calendar = Calendar.getInstance()
30+
return simpleDateFormat.format(calendar.time)
31+
}
32+
}
33+
34+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.android.tvflix.domain
2+
3+
import com.android.tvflix.db.favouriteshow.FavoriteShow
4+
import com.android.tvflix.di.IoDispatcher
5+
import com.android.tvflix.favorite.FavoriteShowsRepository
6+
import com.android.tvflix.network.home.Show
7+
import kotlinx.coroutines.CoroutineDispatcher
8+
import javax.inject.Inject
9+
10+
class RemoveFromFavoritesUseCase
11+
@Inject
12+
constructor(
13+
private val favoriteShowsRepository: FavoriteShowsRepository,
14+
@IoDispatcher ioDispatcher: CoroutineDispatcher
15+
) : SuspendUseCase<FavoriteShow, Unit>(ioDispatcher) {
16+
override suspend fun execute(parameters: FavoriteShow) {
17+
favoriteShowsRepository.removeFromFavorites(parameters)
18+
}
19+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.android.tvflix.domain
2+
3+
import kotlinx.coroutines.CoroutineDispatcher
4+
import kotlinx.coroutines.withContext
5+
6+
/**
7+
* Executes business logic synchronously or asynchronously using Coroutines.
8+
*
9+
* The [execute] method of [SuspendUseCase] is a suspend function
10+
*/
11+
abstract class SuspendUseCase<in P, R>(private val coroutineDispatcher: CoroutineDispatcher) {
12+
13+
/** Executes the use case asynchronously and returns a [Result].
14+
*
15+
* @return a [Result].
16+
*
17+
* @param parameters the input parameters to run the use case with
18+
*/
19+
val tag: String = this.javaClass.simpleName
20+
21+
suspend operator fun invoke(parameters: P): R {
22+
// Moving all use case's executions to the injected dispatcher
23+
// In production code, this is usually the Default dispatcher (background thread)
24+
// In tests, this becomes a TestCoroutineDispatcher
25+
return withContext(coroutineDispatcher) {
26+
execute(parameters)
27+
}
28+
}
29+
30+
/**
31+
* Override this to set the code to be executed.
32+
*/
33+
@Throws(RuntimeException::class)
34+
protected abstract suspend fun execute(parameters: P): R
35+
}

app/src/main/java/com/android/tvflix/favorite/FavoriteShowsActivity.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import dagger.hilt.android.AndroidEntryPoint
2222
import kotlinx.coroutines.flow.collect
2323

2424
@AndroidEntryPoint
25-
class FavoriteShowsActivity : AppCompatActivity(), FavoriteShowsAdapter.Callback {
25+
class FavoriteShowsActivity : AppCompatActivity() {
2626
private val favoriteShowsViewModel: FavoriteShowsViewModel by viewModels()
2727
private val binding by lazy { ActivityFavoriteShowsBinding.inflate(layoutInflater) }
2828

@@ -62,7 +62,7 @@ class FavoriteShowsActivity : AppCompatActivity(), FavoriteShowsAdapter.Callback
6262
binding.progress.isVisible = false
6363
val layoutManager = GridLayoutManager(this, COLUMNS_COUNT)
6464
binding.shows.layoutManager = layoutManager
65-
val favoriteShowsAdapter = FavoriteShowsAdapter(favoriteShows.toMutableList(), this)
65+
val favoriteShowsAdapter = FavoriteShowsAdapter(favoriteShows.toMutableList())
6666
binding.shows.adapter = favoriteShowsAdapter
6767
val spacing = resources.getDimensionPixelSize(R.dimen.show_grid_spacing)
6868
binding.shows.addItemDecoration(GridItemDecoration(spacing, COLUMNS_COUNT))
@@ -81,10 +81,6 @@ class FavoriteShowsActivity : AppCompatActivity(), FavoriteShowsAdapter.Callback
8181
binding.favoriteHint.isVisible = true
8282
}
8383

84-
override fun onFavoriteClicked(show: FavoriteShow) {
85-
favoriteShowsViewModel.onFavoriteClick(show)
86-
}
87-
8884
companion object {
8985
private const val FAVORITE_ICON_START_OFFSET = 13
9086
private const val FAVORITE_ICON_END_OFFSET = 14

app/src/main/java/com/android/tvflix/favorite/FavoriteShowsAdapter.kt

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,48 +13,23 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
1313
import com.bumptech.glide.request.RequestOptions
1414

1515
class FavoriteShowsAdapter(
16-
private val favoriteShows: MutableList<FavoriteShow>,
17-
private val callback: Callback
16+
private val favoriteShows: MutableList<FavoriteShow>
1817
) : RecyclerView.Adapter<FavoriteShowsAdapter.FavoriteShowHolder>() {
1918

2019
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavoriteShowHolder {
2120
val layoutInflater = LayoutInflater.from(parent.context)
2221
val showListItemBinding = ShowListItemBinding.inflate(layoutInflater, parent, false)
2322
val holder = FavoriteShowHolder(showListItemBinding)
24-
holder.binding.favorite.setOnClickListener { onFavouriteIconClicked(holder.absoluteAdapterPosition) }
2523
holder.binding.showFavoriteIcon = false
2624
return holder
2725
}
2826

29-
private fun onFavouriteIconClicked(position: Int) {
30-
if (position != RecyclerView.NO_POSITION) {
31-
val show = favoriteShows[position]
32-
val updatedShow = show.copy(isFavorite = !show.isFavorite)
33-
favoriteShows[position] = updatedShow
34-
notifyItemChanged(position)
35-
callback.onFavoriteClicked(show)
36-
}
37-
}
38-
3927
override fun onBindViewHolder(holder: FavoriteShowHolder, position: Int) {
4028
val favoriteShow = favoriteShows[position]
4129
Glide.with(holder.itemView.context).load(favoriteShow.imageUrl)
4230
.apply(RequestOptions.placeholderOf(R.color.grey))
4331
.transition(DrawableTransitionOptions.withCrossFade())
4432
.into(holder.binding.showImage)
45-
configureFavoriteIcon(holder.binding.favorite, favoriteShow.isFavorite)
46-
}
47-
48-
private fun configureFavoriteIcon(favoriteIcon: ImageView, favorite: Boolean) {
49-
if (favorite) {
50-
val favoriteDrawable = AppCompatResources
51-
.getDrawable(favoriteIcon.context, R.drawable.favorite)
52-
favoriteIcon.setImageDrawable(favoriteDrawable)
53-
} else {
54-
val unFavoriteDrawable = AppCompatResources
55-
.getDrawable(favoriteIcon.context, R.drawable.favorite_border)
56-
favoriteIcon.setImageDrawable(unFavoriteDrawable)
57-
}
5833
}
5934

6035
override fun getItemCount(): Int {
@@ -63,8 +38,4 @@ class FavoriteShowsAdapter(
6338

6439
class FavoriteShowHolder(val binding: ShowListItemBinding) :
6540
RecyclerView.ViewHolder(binding.root)
66-
67-
interface Callback {
68-
fun onFavoriteClicked(show: FavoriteShow)
69-
}
7041
}

0 commit comments

Comments
 (0)