Skip to content

Commit

Permalink
Merge branch 'development' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
terry1921 authored Mar 18, 2023
2 parents 5014de9 + 0cd2c72 commit f4f6d1f
Show file tree
Hide file tree
Showing 24 changed files with 446 additions and 4 deletions.
10 changes: 10 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,12 @@ android {

dependencies {
// modules
implementation(project(":core-data"))

// modules for unit test
testImplementation(project(":core-network"))
testImplementation(project(":core-test"))
androidTestImplementation(project(":core-test"))

// androidx
implementation(libs.material)
Expand All @@ -86,6 +90,9 @@ dependencies {
// whatIf
implementation(libs.whatif)

// timber
implementation(libs.timber)

// bundler
implementation(libs.bundler)

Expand All @@ -94,6 +101,9 @@ dependencies {
implementation(libs.baseAdapter)
implementation(libs.progressView)

// transformation animation
implementation(libs.transformationLayout)

// unit test
testImplementation(libs.junit)
testImplementation(libs.turbine)
Expand Down
13 changes: 12 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,20 @@
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:name=".MainApp"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyTemplate"
tools:targetApi="31" />
tools:targetApi="31">
<activity
android:name=".ui.main.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
8 changes: 8 additions & 0 deletions app/src/main/kotlin/com/mx/rockstar/mytemplate/MainApp.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.mx.rockstar.mytemplate

import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class MainApp : Application() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.mx.rockstar.mytemplate.binding

import android.view.View
import android.widget.Toast
import androidx.databinding.BindingAdapter
import com.skydoves.whatif.whatIf
import com.skydoves.whatif.whatIfNotNullOrEmpty

object ViewBinding {

@JvmStatic
@BindingAdapter("toast")
fun bindToast(view: View, text: String?) {
text.whatIfNotNullOrEmpty { message ->
Toast.makeText(view.context, message, Toast.LENGTH_SHORT).show()
}
}

@JvmStatic
@BindingAdapter("gone")
fun bindGone(view: View, shouldBeGone: Boolean) {
view.visibility = if (shouldBeGone) {
View.GONE
} else {
View.VISIBLE
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.mx.rockstar.mytemplate.ui.main

import android.os.Bundle
import androidx.activity.viewModels
import androidx.annotation.VisibleForTesting
import com.mx.rockstar.mytemplate.R
import com.mx.rockstar.mytemplate.databinding.LayoutMainBinding
import com.skydoves.bindables.BindingActivity
import com.skydoves.transformationlayout.onTransformationStartContainer
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : BindingActivity<LayoutMainBinding>(R.layout.layout_main) {

@get:VisibleForTesting
internal val viewModel: MainViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
onTransformationStartContainer()
super.onCreate(savedInstanceState)
binding {
vm = viewModel
}
}

override fun onStart() {
super.onStart()
binding.button.setOnClickListener {
viewModel.updateMessage()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.mx.rockstar.mytemplate.ui.main

import androidx.databinding.Bindable
import androidx.lifecycle.viewModelScope
import com.mx.rockstar.mytemplate.core.data.repository.MainRepository
import com.skydoves.bindables.BindingViewModel
import com.skydoves.bindables.asBindingProperty
import com.skydoves.bindables.bindingProperty
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import timber.log.Timber
import javax.inject.Inject

@HiltViewModel
class MainViewModel @Inject constructor(
private val mainRepository: MainRepository
) : BindingViewModel() {

@get:Bindable
var isLoading: Boolean by bindingProperty(false)
private set

@get:Bindable
var message: String? by bindingProperty(null)
private set

private val fetchingIndex: MutableStateFlow<Int> = MutableStateFlow(0)
private val listFlow = fetchingIndex.flatMapLatest { page ->
mainRepository.fetchData(
page = page,
onStart = { isLoading = true },
onComplete = { isLoading = false },
onError = { message = it }
)
}

@get:Bindable
val response: String by listFlow.asBindingProperty(viewModelScope, "")

init {
Timber.d("init MainViewModel")
}

fun updateMessage() {
if (!isLoading) {
message = ""
fetchingIndex.value++
}
}

}
51 changes: 51 additions & 0 deletions app/src/main/res/layout/layout_main.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?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">

<data>
<variable
name="vm"
type="com.mx.rockstar.mytemplate.ui.main.MainViewModel" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.appcompat.widget.AppCompatTextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:gravity="center"
app:gone="@{vm.loading}"
android:text="@{vm.response}"
app:toast="@{vm.message}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@android:string/ok"
android:layout_margin="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>

<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:gone="@{!vm.loading}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

</layout>
1 change: 1 addition & 0 deletions core-data/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
43 changes: 43 additions & 0 deletions core-data/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import com.mx.rockstar.mytemplate.Configuration

@Suppress("DSL_SCOPE_VIOLATION")
plugins {
id(libs.plugins.android.library.get().pluginId)
id(libs.plugins.kotlin.android.get().pluginId)
id(libs.plugins.kotlin.kapt.get().pluginId)
}

android {
compileSdk = Configuration.compileSdk

defaultConfig {
minSdk = Configuration.minSdk
targetSdk = Configuration.targetSdk
}
}

dependencies {
api(project(":core-model"))
implementation(project(":core-network"))
//implementation(project(":core-database"))
testImplementation(project(":core-test"))

// coroutines
implementation(libs.coroutines)
testImplementation(libs.coroutines)
testImplementation(libs.coroutines.test)

// network
implementation(libs.sandwich)

// di
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)

// unit test
testImplementation(libs.junit)
testImplementation(libs.turbine)
testImplementation(libs.androidx.test.core)
testImplementation(libs.mockito.kotlin)
testImplementation(libs.mockito.inline)
}
2 changes: 2 additions & 0 deletions core-data/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.mx.rockstar.mytemplate.core.data"/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.mx.rockstar.mytemplate.core.data.di

import com.mx.rockstar.mytemplate.core.data.repository.MainRepository
import com.mx.rockstar.mytemplate.core.data.repository.MainRepositoryImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
internal interface DataModule {

@Binds
fun bindsMainRepository(mainRepositoryImpl: MainRepositoryImpl): MainRepository

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.mx.rockstar.mytemplate.core.data.repository

import androidx.annotation.WorkerThread
import kotlinx.coroutines.flow.Flow

interface MainRepository {

@WorkerThread
fun fetchData(
page: Int,
onStart: () -> Unit,
onComplete: () -> Unit,
onError: (String?) -> Unit
): Flow<String>

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.mx.rockstar.mytemplate.core.data.repository

import androidx.annotation.VisibleForTesting
import androidx.annotation.WorkerThread
import com.mx.rockstar.mytemplate.core.network.AppDispatcher
import com.mx.rockstar.mytemplate.core.network.Dispatcher
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.*
import javax.inject.Inject

@VisibleForTesting
class MainRepositoryImpl @Inject constructor(
@Dispatcher(AppDispatcher.IO) private val ioDispatcher: CoroutineDispatcher
) : MainRepository {

@WorkerThread
override fun fetchData(
page: Int,
onStart: () -> Unit,
onComplete: () -> Unit,
onError: (String?) -> Unit
): Flow<String> = flow {
kotlinx.coroutines.delay(1000)
if (page == 0) emit("Comenzamos...")
else if (page <= 10) emit("Flujo #${page} Terminando")
else onError("Ya son Muchas...")
}.onStart { onStart() }.onCompletion { onComplete() }.flowOn(ioDispatcher)

}
1 change: 1 addition & 0 deletions core-model/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
27 changes: 27 additions & 0 deletions core-model/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import com.mx.rockstar.mytemplate.Configuration

@Suppress("DSL_SCOPE_VIOLATION")
plugins {
id(libs.plugins.android.library.get().pluginId)
id(libs.plugins.kotlin.android.get().pluginId)
id(libs.plugins.kotlin.parcelize.get().pluginId)
id(libs.plugins.ksp.get().pluginId) version libs.versions.ksp.get()
}

android {
compileSdk = Configuration.compileSdk

defaultConfig {
minSdk = Configuration.minSdk
targetSdk = Configuration.targetSdk
}
}

dependencies {
// json parsing
implementation(libs.moshi)
ksp(libs.moshi.codegen)

// logger
api(libs.timber)
}
2 changes: 2 additions & 0 deletions core-model/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.mx.rockstar.mytemplate.core.model"/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.mx.rockstar.mytemplate.core.model

data class DataModel(
var message: String? = null
)
Loading

0 comments on commit f4f6d1f

Please sign in to comment.