Feature/styling (#36)

* Working with material styles

* Replaced deprecated ViewModelProviders.of and applied base styles with material components

* Various code style fixes and styles.xml improvements
This commit is contained in:
Melih Aksoy
2019-09-13 14:09:28 +02:00
committed by GitHub
parent 5a10edce17
commit 99a2abf050
58 changed files with 523 additions and 464 deletions

View File

@@ -1,5 +1,4 @@
package com.melih.repository
const val DEFAULT_NAME = "Default name"
const val EMPTY_STRING = ""
const val DEFAULT_IMAGE_SIZE = 480
internal const val DEFAULT_NAME = "Default name"
internal const val EMPTY_STRING = ""

View File

@@ -4,10 +4,13 @@ import com.melih.repository.entities.LaunchEntity
import com.melih.repository.interactors.base.Result
/**
* Abstract class to create contract in sources to seperate low level business logic from build and return type
* Contract for sources to seperate low level business logic from build and return type
*/
abstract class Repository {
//region Abstractions
internal abstract suspend fun getNextLaunches(count: Int, page: Int): Result<List<LaunchEntity>>
internal abstract suspend fun getLaunchById(id: Long): Result<LaunchEntity>
//endregion
}

View File

@@ -18,11 +18,16 @@ import javax.inject.Inject
@UseExperimental(ExperimentalCoroutinesApi::class)
class GetLaunchDetails @Inject constructor() : BaseInteractor<LaunchEntity, GetLaunchDetails.Params>() {
//region Properties
@field:Inject
internal lateinit var networkSource: NetworkSource
@field:Inject
internal lateinit var persistenceSource: PersistenceSource
//endregion
//region Functions
override suspend fun FlowCollector<Result<LaunchEntity>>.run(params: Params) {
val result = persistenceSource.getLaunchById(params.id)
@@ -42,6 +47,7 @@ class GetLaunchDetails @Inject constructor() : BaseInteractor<LaunchEntity, GetL
emit(result)
}
}
//endregion
data class Params(
val id: Long

View File

@@ -19,11 +19,16 @@ const val DEFAULT_LAUNCHES_AMOUNT = 15
@UseExperimental(ExperimentalCoroutinesApi::class)
class GetLaunches @Inject constructor() : BaseInteractor<List<LaunchEntity>, GetLaunches.Params>() {
//region Properties
@field:Inject
internal lateinit var networkSource: NetworkSource
@field:Inject
internal lateinit var persistenceSource: PersistenceSource
//endregion
//region Functions
override suspend fun FlowCollector<Result<List<LaunchEntity>>>.run(params: Params) {
@@ -40,6 +45,7 @@ class GetLaunches @Inject constructor() : BaseInteractor<List<LaunchEntity>, Get
}
}
}
//endregion
data class Params(
val count: Int = DEFAULT_LAUNCHES_AMOUNT,

View File

@@ -13,12 +13,12 @@ import kotlinx.coroutines.flow.flowOn
@UseExperimental(ExperimentalCoroutinesApi::class)
abstract class BaseInteractor<T, in P : InteractorParameters> {
// region Abstractions
//region Abstractions
protected abstract suspend fun FlowCollector<Result<T>>.run(params: P)
// endregion
//endregion
// region Functions
//region Functions
operator fun invoke(params: P) =
flow<Result<T>> {
@@ -26,7 +26,7 @@ abstract class BaseInteractor<T, in P : InteractorParameters> {
run(params)
emit(State.Loaded())
}.flowOn(Dispatchers.IO)
// endregion
//endregion
}
/**

View File

@@ -9,6 +9,8 @@ import com.melih.repository.R
*/
sealed class Reason(@StringRes val messageRes: Int)
//region Subclasses
class NetworkError : Reason(R.string.reason_network)
class EmptyResultError : Reason(R.string.reason_empty_body)
class GenericError : Reason(R.string.reason_generic)
@@ -16,3 +18,4 @@ class ResponseError : Reason(R.string.reason_response)
class TimeoutError : Reason(R.string.reason_timeout)
class PersistenceEmpty : Reason(R.string.reason_persistance_empty)
class NoNetworkPersistenceEmpty : Reason(R.string.reason_no_network_persistance_empty)
//endregion

View File

@@ -9,7 +9,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
@UseExperimental(ExperimentalCoroutinesApi::class)
sealed class Result<out T>
// region Subclasses
//region Subclasses
class Success<out T>(val successData: T) : Result<T>()
class Failure(val errorData: Reason) : Result<Nothing>()
@@ -18,9 +18,9 @@ sealed class State : Result<Nothing>() {
class Loading : State()
class Loaded : State()
}
// endregion
//endregion
// region Extensions
//region Extensions
inline fun <T> Result<T>.handle(stateBlock: (State) -> Unit, failureBlock: (Reason) -> Unit, successBlock: (T) -> Unit) {
when (this) {
@@ -50,4 +50,4 @@ inline fun <T> Result<T>.onState(stateBlock: (State) -> Unit): Result<T> {
return this
}
// endregion
//endregion

View File

@@ -12,6 +12,8 @@ import retrofit2.http.Query
*/
internal interface Api {
//region Get
@GET("launch/next/{count}")
suspend fun getNextLaunches(
@Path("count") count: Int,
@@ -22,4 +24,5 @@ internal interface Api {
suspend fun getLaunchById(
@Path("id") id: Long
): Response<LaunchEntity>
//endregion
}

View File

@@ -16,7 +16,7 @@ internal const val TIMEOUT_DURATION = 7L
internal class ApiImpl @Inject constructor() : Api {
// region Properties
//region Properties
private val service by lazy {
val moshi = Moshi.Builder()
@@ -39,7 +39,9 @@ internal class ApiImpl @Inject constructor() : Api {
.build()
.create(Api::class.java)
}
// endregion
//endregion
//region Functions
override suspend fun getNextLaunches(
count: Int,
@@ -51,4 +53,5 @@ internal class ApiImpl @Inject constructor() : Api {
id: Long
): Response<LaunchEntity> =
service.getLaunchById(id)
//endregion
}

View File

@@ -28,6 +28,8 @@ const val DB_NAME = "LaunchesDB"
)
internal abstract class LaunchesDatabase : RoomDatabase() {
//region Companion
companion object {
private lateinit var instance: LaunchesDatabase
@@ -42,6 +44,10 @@ internal abstract class LaunchesDatabase : RoomDatabase() {
}
}
//endregion
//region Abstractions
internal abstract val launchesDao: LaunchesDao
//endregion
}

View File

@@ -10,13 +10,19 @@ import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
*/
abstract class BaseConverter<T> {
//region Abstractions
abstract fun getAdapter(moshi: Moshi): JsonAdapter<T>
//endregion
//region Properties
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
//endregion
abstract fun getAdapter(moshi: Moshi): JsonAdapter<T>
// region Functions
//region Functions
@TypeConverter
fun convertFrom(item: T) =
@@ -25,5 +31,5 @@ abstract class BaseConverter<T> {
@TypeConverter
fun convertTo(string: String) =
getAdapter(moshi).fromJson(string)
// endregion
//endregion
}

View File

@@ -10,13 +10,19 @@ import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
*/
abstract class BaseListConverter<T> {
//region Abstractions
abstract fun getAdapter(moshi: Moshi): JsonAdapter<List<T>>
//endregion
//region Properties
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
//endregion
abstract fun getAdapter(moshi: Moshi): JsonAdapter<List<T>>
// region Functions
//region Functions
@TypeConverter
fun convertFrom(items: List<T>) =
@@ -25,5 +31,5 @@ abstract class BaseListConverter<T> {
@TypeConverter
fun convertTo(string: String): List<T>? =
getAdapter(moshi).fromJson(string)
// endregion
//endregion
}

View File

@@ -9,6 +9,7 @@ import com.squareup.moshi.Moshi
* Converts [location][LocationEntity]
*/
class LocationConverter : BaseConverter<LocationEntity>() {
override fun getAdapter(moshi: Moshi): JsonAdapter<LocationEntity> =
LocationEntityJsonAdapter(moshi)
}

View File

@@ -9,6 +9,7 @@ import com.squareup.moshi.Moshi
* Converts [rocket][RocketEntity]
*/
class RocketConverter : BaseConverter<RocketEntity>() {
override fun getAdapter(moshi: Moshi): JsonAdapter<RocketEntity> =
RocketEntityJsonAdapter(moshi)
RocketEntityJsonAdapter(moshi)
}

View File

@@ -12,7 +12,7 @@ import com.melih.repository.entities.LaunchEntity
@Dao
internal abstract class LaunchesDao {
// region Queries
//region Queries
@Query("SELECT * FROM Launches ORDER BY launchStartTime DESC LIMIT :count OFFSET :page*:count")
abstract suspend fun getLaunches(count: Int, page: Int): List<LaunchEntity>
@@ -22,14 +22,14 @@ internal abstract class LaunchesDao {
@Query("DELETE FROM Launches")
abstract suspend fun nukeLaunches()
// endregion
//endregion
// region Insertion
//region Insertion
@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract suspend fun saveLaunches(launches: List<LaunchEntity>)
@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract suspend fun saveLaunch(launch: LaunchEntity)
// endregion
//endregion
}

View File

@@ -1,7 +1,6 @@
package com.melih.repository.sources
import android.net.NetworkInfo
import com.melih.repository.DEFAULT_IMAGE_SIZE
import com.melih.repository.Repository
import com.melih.repository.entities.LaunchEntity
import com.melih.repository.interactors.DEFAULT_LAUNCHES_AMOUNT
@@ -19,6 +18,8 @@ import java.io.IOException
import javax.inject.Inject
import javax.inject.Provider
private const val DEFAULT_IMAGE_SIZE = 480
/**
* NetworkSource for fetching results using api and wrapping them as contracted in [repository][Repository],
* returning either [failure][Failure] with proper [reason][Reason] or [success][Success] with data
@@ -27,16 +28,17 @@ internal class NetworkSource @Inject constructor(
private val apiImpl: ApiImpl,
private val networkInfoProvider: Provider<NetworkInfo>
) : Repository() {
// region Properties
//region Properties
private val isNetworkConnected: Boolean
get() {
val networkInfo = networkInfoProvider.get()
return networkInfo != null && networkInfo.isConnected
}
// endregion
//endregion
// region Functions
//region Functions
override suspend fun getNextLaunches(count: Int, page: Int): Result<List<LaunchEntity>> =
safeExecute({
@@ -73,8 +75,8 @@ internal class NetworkSource @Inject constructor(
}
}
private suspend inline fun <T, R> safeExecute(
block: suspend () -> Response<T>,
private inline fun <T, R> safeExecute(
block: () -> Response<T>,
transform: (T) -> R
) =
if (isNetworkConnected) {
@@ -112,5 +114,5 @@ internal class NetworkSource @Inject constructor(
} catch (e: Exception) {
imageUrl
}
// endregion
//endregion
}

View File

@@ -16,7 +16,8 @@ import javax.inject.Inject
internal class PersistenceSource @Inject constructor(
ctx: Context
) : Repository() {
// region Functions
//region Functions
private val launchesDatabase = LaunchesDatabase.getInstance(ctx)
@@ -45,5 +46,5 @@ internal class PersistenceSource @Inject constructor(
internal suspend fun saveLaunch(launch: LaunchEntity) {
launchesDatabase.launchesDao.saveLaunch(launch)
}
// endregion
//endregion
}