WIP: feature/abstractions (#45)

* Abstraction layer backup

* Removed DataEntity, was unnecessary for now

* Separated network, persistence, entities and interaction, closes #29

* Renamed binding

* Removed build files, example tests

Removed build files, example tests

* Fixed build files were not being ignored all around app

* Updated CI ymls

* Small changes

* Fixed legacy repository package names

* Fixed CQ findings

* Updated Fastlane

* Packaging changes and version upgrades

* Removed core from interactors

* Version bumps

* Added new module graph
This commit is contained in:
Melih Aksoy
2019-10-30 17:27:53 +01:00
committed by GitHub
parent 83e39400a9
commit 88022629e1
103 changed files with 1098 additions and 921 deletions

View File

@@ -14,7 +14,5 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':repository')
testImplementation testLibraries.coroutinesTest
}

View File

@@ -0,0 +1,10 @@
package com.melih.launches.data
import com.melih.abstractions.data.ViewEntity
data class LaunchDetailItem(
val id: Long,
val imageUrl: String,
val rocketName: String,
val missionDescription: String
) : ViewEntity

View File

@@ -0,0 +1,18 @@
package com.melih.launches.data
import com.melih.abstractions.mapper.Mapper
import com.melih.definitions.entities.LaunchEntity
import javax.inject.Inject
class LaunchDetailMapper @Inject constructor() : Mapper<LaunchEntity, LaunchDetailItem>() {
override fun convert(launchEntity: LaunchEntity) =
with(launchEntity) {
LaunchDetailItem(
id,
rocket.imageURL,
rocket.name,
if (!missions.isNullOrEmpty()) missions[0].description else ""
)
}
}

View File

@@ -2,11 +2,15 @@ package com.melih.detail.di.modules
import androidx.lifecycle.ViewModel
import androidx.navigation.fragment.navArgs
import com.melih.abstractions.mapper.Mapper
import com.melih.core.di.keys.ViewModelKey
import com.melih.definitions.entities.LaunchEntity
import com.melih.detail.ui.DetailFragment
import com.melih.detail.ui.DetailFragmentArgs
import com.melih.detail.ui.DetailViewModel
import com.melih.repository.interactors.GetLaunchDetails
import com.melih.interactors.GetLaunchDetails
import com.melih.launches.data.LaunchDetailItem
import com.melih.launches.data.LaunchDetailMapper
import dagger.Binds
import dagger.Module
import dagger.Provides
@@ -21,6 +25,9 @@ abstract class DetailFragmentModule {
@IntoMap
@ViewModelKey(DetailViewModel::class)
abstract fun detailViewModel(detailViewModel: DetailViewModel): ViewModel
@Binds
abstract fun detailMapper(mapper: LaunchDetailMapper): Mapper<LaunchEntity, LaunchDetailItem>
//endregion
@Module

View File

@@ -1,34 +1,31 @@
package com.melih.detail.ui
import androidx.lifecycle.Transformations.map
import com.melih.abstractions.deliverable.handle
import com.melih.core.base.viewmodel.BaseViewModel
import com.melih.repository.entities.LaunchEntity
import com.melih.repository.interactors.GetLaunchDetails
import com.melih.repository.interactors.base.handle
import com.melih.interactors.GetLaunchDetails
import com.melih.launches.data.LaunchDetailItem
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import javax.inject.Inject
class DetailViewModel @Inject constructor(
private val getLaunchDetails: GetLaunchDetails,
private val getLaunchDetails: GetLaunchDetails<LaunchDetailItem>,
private val getLaunchDetailsParams: GetLaunchDetails.Params
) : BaseViewModel<LaunchEntity>() {
) : BaseViewModel<LaunchDetailItem>() {
//region Properties
val rocketName = map(successData) {
it.rocket.name
it.rocketName
}
val description = map(successData) {
if (it.missions.isEmpty()) {
""
} else {
it.missions[0].description
}
it.missionDescription
}
val imageUrl = map(successData) {
it.rocket.imageURL
it.imageUrl
}
//endregion

View File

@@ -1,69 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<layout
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">
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">
<data class="DetailBinding">
<data class="DetailBinding">
<variable
name="viewModel"
type="com.melih.detail.ui.DetailViewModel" />
</data>
<variable
name="viewModel"
type="com.melih.detail.ui.DetailViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imgRocket"
imageUrl="@{viewModel.imageUrl}"
android:layout_width="0dp"
android:layout_height="220dp"
android:layout_marginStart="@dimen/padding_standard"
android:layout_marginLeft="@dimen/padding_standard"
android:layout_marginTop="@dimen/padding_standard"
android:layout_marginEnd="@dimen/padding_standard"
android:layout_marginRight="@dimen/padding_standard"
android:contentDescription="@string/cd_rocket_image"
android:scaleType="centerCrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/avatars[14]" />
<ImageView
android:id="@+id/imgRocket"
imageUrl="@{viewModel.imageUrl}"
android:layout_width="0dp"
android:layout_height="220dp"
android:layout_marginStart="@dimen/padding_standard"
android:layout_marginLeft="@dimen/padding_standard"
android:layout_marginTop="@dimen/padding_standard"
android:layout_marginEnd="@dimen/padding_standard"
android:layout_marginRight="@dimen/padding_standard"
android:contentDescription="@string/cd_rocket_image"
android:scaleType="centerCrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/avatars[14]" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/tvTitle"
style="@style/AppTheme.TextViewStyle.Title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/padding_standard"
android:layout_marginLeft="@dimen/padding_standard"
android:layout_marginTop="@dimen/padding_standard"
android:layout_marginEnd="@dimen/padding_standard"
android:layout_marginRight="@dimen/padding_standard"
android:text="@{viewModel.rocketName}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imgRocket"
tools:text="@sample/launches.json/launches/name" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/tvTitle"
style="@style/AppTheme.TextViewStyle.Title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/padding_standard"
android:layout_marginLeft="@dimen/padding_standard"
android:layout_marginTop="@dimen/padding_standard"
android:layout_marginEnd="@dimen/padding_standard"
android:layout_marginRight="@dimen/padding_standard"
android:text="@{viewModel.rocketName}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imgRocket"
tools:text="@sample/launches.json/launches/name" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/tvDescription"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="@dimen/padding_standard"
android:layout_marginLeft="@dimen/padding_standard"
android:layout_marginTop="@dimen/padding_standard"
android:layout_marginEnd="@dimen/padding_standard"
android:layout_marginRight="@dimen/padding_standard"
android:layout_marginBottom="@dimen/padding_standard"
android:text="@{viewModel.description}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvTitle"
tools:text="@sample/launches.json/launches/missions/description" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.textview.MaterialTextView
android:id="@+id/tvDescription"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="@dimen/padding_standard"
android:layout_marginLeft="@dimen/padding_standard"
android:layout_marginTop="@dimen/padding_standard"
android:layout_marginEnd="@dimen/padding_standard"
android:layout_marginRight="@dimen/padding_standard"
android:layout_marginBottom="@dimen/padding_standard"
android:text="@{viewModel.description}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvTitle"
tools:text="@sample/launches.json/launches/missions/description" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -1,7 +1,8 @@
package com.melih.detail
import com.melih.detail.ui.DetailViewModel
import com.melih.repository.interactors.GetLaunchDetails
import com.melih.interactors.GetLaunchDetails
import com.melih.launches.data.LaunchDetailItem
import io.mockk.mockk
import io.mockk.slot
import io.mockk.spyk
@@ -19,7 +20,7 @@ import org.junit.jupiter.api.Test
@UseExperimental(ExperimentalCoroutinesApi::class)
class DetailViewModelTest : BaseTestWithMainThread() {
private val getLaunchDetails: GetLaunchDetails = mockk(relaxed = true)
private val getLaunchDetails: GetLaunchDetails<LaunchDetailItem> = mockk(relaxed = true)
private val getLaunchDetailsParams = GetLaunchDetails.Params(1013)
private val viewModel = spyk(DetailViewModel(getLaunchDetails, getLaunchDetailsParams))