From 2aa57b105d440a6475c7f4ccfb440f9893fc2e8d Mon Sep 17 00:00:00 2001 From: MarcinMoskala Date: Sat, 18 Mar 2017 10:32:36 +0100 Subject: [PATCH 1/6] Changes according to https://kotlinlang.org/docs/reference/coding-conventions.html Bump kotlin version to 1.1 --- .../data/network/NetworkInteractorImpl.kt | 21 ++++++++++--------- .../data/remote/ApiConstants.kt | 13 +++++------- .../data/remote/ApiModule.kt | 7 ++++--- .../data/remote/GithubApiService.kt | 8 ++++--- .../data/remote/model/GithubApiModels.kt | 10 +-------- .../extensions/ViewExtensions.kt | 12 +++++------ .../ui/base/ViewModelActivity.kt | 3 ++- .../ui/base/ViewModelLoader.kt | 7 +++++-- .../kotlinboilerplate/ui/list/ListActivity.kt | 10 +++------ .../ui/list/ListViewModel.kt | 6 ++++-- .../ui/misc/SimpleDividerItemDecoration.kt | 4 +++- build.gradle | 2 +- 12 files changed, 49 insertions(+), 54 deletions(-) diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/network/NetworkInteractorImpl.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/network/NetworkInteractorImpl.kt index 1eb7151..5395385 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/network/NetworkInteractorImpl.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/network/NetworkInteractorImpl.kt @@ -6,17 +6,18 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class NetworkInteractorImpl @Inject constructor(private val connectivityManager: - ConnectivityManager) : NetworkInteractor { +class NetworkInteractorImpl @Inject constructor( + private val connectivityManager: ConnectivityManager +) : NetworkInteractor { - override fun hasNetworkConnection(): Boolean = connectivityManager.activeNetworkInfo?.isConnectedOrConnecting ?: false + override fun hasNetworkConnection(): Boolean = + connectivityManager.activeNetworkInfo?.isConnectedOrConnecting ?: false - override fun hasNetworkConnectionCompletable(): Completable { - if (hasNetworkConnection()) { - return Completable.complete() - } else { - return Completable.error { NetworkInteractor.NetworkUnavailableException() } - } - } + override fun hasNetworkConnectionCompletable(): Completable = + if (hasNetworkConnection()) { + Completable.complete() + } else { + Completable.error { NetworkInteractor.NetworkUnavailableException() } + } } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/ApiConstants.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/ApiConstants.kt index 69ea16d..59c3592 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/ApiConstants.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/ApiConstants.kt @@ -1,12 +1,9 @@ package io.github.plastix.kotlinboilerplate.data.remote -class ApiConstants { - companion object { - const val GITHUB_API_BASE_ENDPOINT = "https://api.github.com" - - const val SEARCH_QUERY_KOTLIN = "language:kotlin" - const val SEARCH_SORT_STARS = "stars" - const val SEARCH_ORDER_DESCENDING = "desc" - } +object ApiConstants { + const val GITHUB_API_BASE_ENDPOINT = "https://api.github.com" + const val SEARCH_QUERY_KOTLIN = "language:kotlin" + const val SEARCH_SORT_STARS = "stars" + const val SEARCH_ORDER_DESCENDING = "desc" } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/ApiModule.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/ApiModule.kt index 3fb920b..0b70530 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/ApiModule.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/ApiModule.kt @@ -16,14 +16,15 @@ class ApiModule { } @Provides @Singleton - fun provideRetrofit(rxJavaCallAdapterFactory: RxJava2CallAdapterFactory, - gsonConverterFactory: GsonConverterFactory): Retrofit { + fun provideRetrofit( + rxJavaCallAdapterFactory: RxJava2CallAdapterFactory, + gsonConverterFactory: GsonConverterFactory + ): Retrofit { return Retrofit.Builder() .baseUrl(ApiConstants.GITHUB_API_BASE_ENDPOINT) .addCallAdapterFactory(rxJavaCallAdapterFactory) .addConverterFactory(gsonConverterFactory) .build() - } @Provides @Singleton diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/GithubApiService.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/GithubApiService.kt index c6b033b..0decf60 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/GithubApiService.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/GithubApiService.kt @@ -8,7 +8,9 @@ import retrofit2.http.Query interface GithubApiService { @GET("/search/repositories") - fun repoSearch(@Query("q") query: String, - @Query("sort") sort: String, - @Query("order") order: String): Single + fun repoSearch( + @Query("q") query: String, + @Query("sort") sort: String, + @Query("order") order: String + ): Single } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/model/GithubApiModels.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/model/GithubApiModels.kt index 21108ae..950ef6a 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/model/GithubApiModels.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/model/GithubApiModels.kt @@ -4,30 +4,23 @@ import android.os.Parcel import com.google.gson.annotations.SerializedName data class SearchResponse( - @SerializedName("total_count") val count: Int, - @SerializedName("items") val repos: List ) data class Repo( - val name: String, - @SerializedName("full_name") val fullName: String, - val owner: Owner, - val description: String, - @SerializedName("stargazers_count") val stars: Int, - val forks: Int ) : DefaultParcelable { + override fun writeToParcel(dest: Parcel, flags: Int) { dest.write(name, fullName, owner, description, stars, forks) } @@ -42,7 +35,6 @@ data class Repo( data class Owner( @SerializedName("login") val name: String, - @SerializedName("avatar_url") val avatarUrl: String ) : DefaultParcelable { diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/extensions/ViewExtensions.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/extensions/ViewExtensions.kt index 7ec3cad..e592095 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/extensions/ViewExtensions.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/extensions/ViewExtensions.kt @@ -10,13 +10,11 @@ import android.view.ViewGroup import android.widget.ImageView import com.squareup.picasso.Picasso -fun View.show() { - visibility = View.VISIBLE -} - -fun View.hide() { - visibility = View.GONE -} +var View.isVisible: Boolean + get() = visibility == View.VISIBLE + set(value) { + visibility = if(value) View.VISIBLE else View.GONE + } fun Context.inflateLayout(layoutResId: Int): View { return inflateView(this, layoutResId, null, false) diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModelActivity.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModelActivity.kt index adfa3a1..4406602 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModelActivity.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModelActivity.kt @@ -9,7 +9,8 @@ import android.support.v4.content.Loader import javax.inject.Inject import javax.inject.Provider -abstract class ViewModelActivity : BaseActivity(), +abstract class ViewModelActivity + : BaseActivity(), LoaderManager.LoaderCallbacks { private val LOADER_ID = 1 diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModelLoader.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModelLoader.kt index 9e5cac7..54d466f 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModelLoader.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModelLoader.kt @@ -6,8 +6,11 @@ import io.github.plastix.kotlinboilerplate.ui.ActivityScope import javax.inject.Inject import javax.inject.Provider -class ViewModelLoader @Inject constructor(@ActivityScope context: Context, - private val viewModelFactory: Provider) : Loader(context) { +class ViewModelLoader @Inject constructor( + @ActivityScope context: Context, + private val viewModelFactory: Provider +) : Loader(context) { + private var viewModel: T? = null override fun onStartLoading() { diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListActivity.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListActivity.kt index 846f17d..361c5ad 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListActivity.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListActivity.kt @@ -10,8 +10,7 @@ import io.github.plastix.kotlinboilerplate.ApplicationComponent import io.github.plastix.kotlinboilerplate.R import io.github.plastix.kotlinboilerplate.data.remote.model.Repo import io.github.plastix.kotlinboilerplate.databinding.ActivityListBinding -import io.github.plastix.kotlinboilerplate.extensions.hide -import io.github.plastix.kotlinboilerplate.extensions.show +import io.github.plastix.kotlinboilerplate.extensions.isVisible import io.github.plastix.kotlinboilerplate.extensions.showSnackbar import io.github.plastix.kotlinboilerplate.ui.base.ViewModelActivity import io.github.plastix.kotlinboilerplate.ui.detail.DetailActivity @@ -103,11 +102,8 @@ class ListActivity : ViewModelActivity() { } private fun updateEmptyView() { - if (adapter.itemCount == 0) { - binding.emptyView.root.show() - } else { - binding.emptyView.root.hide() - } + val thereIsNoItems = adapter.itemCount == 0 + binding.emptyView.root.isVisible = thereIsNoItems } private fun errorNoNetwork() { diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt index cab77d2..c98da82 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt @@ -17,8 +17,10 @@ import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.PublishSubject import javax.inject.Inject -class ListViewModel @Inject constructor(private val apiService: GithubApiService, - private val networkInteractor: NetworkInteractor) : RxViewModel() { +class ListViewModel @Inject constructor( + private val apiService: GithubApiService, + private val networkInteractor: NetworkInteractor +) : RxViewModel() { private var networkRequest: Disposable = Disposables.disposed() diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/misc/SimpleDividerItemDecoration.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/misc/SimpleDividerItemDecoration.kt index d90d694..371b4dc 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/misc/SimpleDividerItemDecoration.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/misc/SimpleDividerItemDecoration.kt @@ -14,7 +14,9 @@ import javax.inject.Inject * * Adapted from https://gist.github.com/polbins/e37206fbc444207c0e92 */ -class SimpleDividerItemDecoration @Inject constructor(@ApplicationQualifier context: Context) : RecyclerView.ItemDecoration() { +class SimpleDividerItemDecoration @Inject constructor( + @ApplicationQualifier context: Context +) : RecyclerView.ItemDecoration() { private val divider: Drawable = ContextCompat.getDrawable(context, R.drawable.line_divider) diff --git a/build.gradle b/build.gradle index 9a600b8..2fb1d13 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.0.6' + ext.kotlin_version = '1.1.0' ext.android_plugin_version = "2.2.3" repositories { From 8e2843aa2348035b8b73b70feb285eb03929ea3b Mon Sep 17 00:00:00 2001 From: MarcinMoskala Date: Sat, 18 Mar 2017 10:39:52 +0100 Subject: [PATCH 2/6] Problem with argument injection setten using lazy property delegate --- .../plastix/kotlinboilerplate/ui/detail/DetailActivity.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/detail/DetailActivity.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/detail/DetailActivity.kt index aebe5db..930bb6c 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/detail/DetailActivity.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/detail/DetailActivity.kt @@ -23,13 +23,9 @@ open class DetailActivity : ViewModelActivity(EXTRA_REPO_OBJECT) } override fun onCreate(savedInstanceState: Bundle?) { - // We need to inject our Book into the Dagger graph - // Thus we need grab it from the intent before we inject dependencies in super.onCreate() - repo = intent.getParcelableExtra(EXTRA_REPO_OBJECT) - super.onCreate(savedInstanceState) setSupportActionBar(binding.detailToolbar) enableToolbarBackButton() From 4bed4af630f9e83e4ec16439fd75786fa964dec7 Mon Sep 17 00:00:00 2001 From: MarcinMoskala Date: Sat, 18 Mar 2017 12:41:57 +0100 Subject: [PATCH 3/6] Deep clean-up --- app/build.gradle | 14 ++- .../kotlinboilerplate/ApplicationComponent.kt | 1 + .../data/network/NetworkInteractorImpl.kt | 10 +- .../data/remote/ApiModule.kt | 24 ++-- .../data/remote/model/Parcels.kt | 3 +- .../extensions/ViewExtensions.kt | 54 +++++---- .../ui/base/AbstractViewModel.kt | 2 +- .../kotlinboilerplate/ui/base/BaseActivity.kt | 6 +- .../kotlinboilerplate/ui/base/ViewModel.kt | 3 +- .../ui/base/ViewModelLoader.kt | 1 - .../ui/detail/DetailActivity.kt | 20 +--- .../ui/detail/DetailBindingAdapter.kt | 2 +- .../kotlinboilerplate/ui/list/ListActivity.kt | 105 +++++++++--------- .../ui/list/ListViewModel.kt | 54 +++++---- .../kotlinboilerplate/ui/list/RepoAdapter.kt | 2 +- .../ui/list/RepoDiffCallback.kt | 18 +-- .../ui/misc/SimpleDividerItemDecoration.kt | 19 ++-- gradle/wrapper/gradle-wrapper.properties | 4 +- 18 files changed, 172 insertions(+), 170 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index af2c1a9..d7ac897 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -90,11 +90,11 @@ dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" // Google Support Libraries - compile 'com.android.support:support-v4:25.1.0' - compile 'com.android.support:support-fragment:25.1.0' - compile 'com.android.support:appcompat-v7:25.1.0' - compile 'com.android.support:design:25.1.0' - compile 'com.android.support:recyclerview-v7:25.1.0' + compile 'com.android.support:support-v4:25.2.0' + compile 'com.android.support:support-fragment:25.2.0' + compile 'com.android.support:appcompat-v7:25.2.0' + compile 'com.android.support:design:25.2.0' + compile 'com.android.support:recyclerview-v7:25.2.0' // RxJava compile 'io.reactivex.rxjava2:rxjava:2.0.0' @@ -118,6 +118,10 @@ dependencies { // Databinding kapt "com.android.databinding:compiler:$android_plugin_version" + // ActivityStarter + compile 'com.github.marcinmoskala.activitystarter:activitystarter:0.30' + kapt 'com.github.marcinmoskala.activitystarter:activitystarter-compiler:0.30' + // Unit Testing testCompile 'junit:junit:4.12' testCompile "org.mockito:mockito-core:1.10.19" diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ApplicationComponent.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ApplicationComponent.kt index c5e79e8..405fbc1 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ApplicationComponent.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ApplicationComponent.kt @@ -23,5 +23,6 @@ interface ApplicationComponent { // Submodule methods // Every screen is its own submodule of the graph and must be added here. fun plus(module: ListModule): ListComponent + fun plus(module: DetailModule): DetailComponent } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/network/NetworkInteractorImpl.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/network/NetworkInteractorImpl.kt index 5395385..b4cc387 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/network/NetworkInteractorImpl.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/network/NetworkInteractorImpl.kt @@ -13,11 +13,9 @@ class NetworkInteractorImpl @Inject constructor( override fun hasNetworkConnection(): Boolean = connectivityManager.activeNetworkInfo?.isConnectedOrConnecting ?: false - override fun hasNetworkConnectionCompletable(): Completable = - if (hasNetworkConnection()) { - Completable.complete() - } else { - Completable.error { NetworkInteractor.NetworkUnavailableException() } - } + override fun hasNetworkConnectionCompletable(): Completable = when { + hasNetworkConnection() -> Completable.complete() + else -> Completable.error { NetworkInteractor.NetworkUnavailableException() } + } } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/ApiModule.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/ApiModule.kt index 0b70530..4b3f498 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/ApiModule.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/ApiModule.kt @@ -11,30 +11,22 @@ import javax.inject.Singleton class ApiModule { @Provides @Singleton - fun provideApiService(retrofit: Retrofit): GithubApiService { - return retrofit.create(GithubApiService::class.java) - } + fun provideApiService(retrofit: Retrofit) = retrofit.create(GithubApiService::class.java)!! @Provides @Singleton fun provideRetrofit( rxJavaCallAdapterFactory: RxJava2CallAdapterFactory, gsonConverterFactory: GsonConverterFactory - ): Retrofit { - return Retrofit.Builder() - .baseUrl(ApiConstants.GITHUB_API_BASE_ENDPOINT) - .addCallAdapterFactory(rxJavaCallAdapterFactory) - .addConverterFactory(gsonConverterFactory) - .build() - } + ) = Retrofit.Builder() + .baseUrl(ApiConstants.GITHUB_API_BASE_ENDPOINT) + .addCallAdapterFactory(rxJavaCallAdapterFactory) + .addConverterFactory(gsonConverterFactory) + .build()!! @Provides @Singleton - fun provideGsonConverterFactory(): GsonConverterFactory { - return GsonConverterFactory.create() - } + fun provideGsonConverterFactory() = GsonConverterFactory.create()!! @Provides @Singleton - fun provideRxJavaCallAdapter(): RxJava2CallAdapterFactory { - return RxJava2CallAdapterFactory.create() - } + fun provideRxJavaCallAdapter() = RxJava2CallAdapterFactory.create()!! } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/model/Parcels.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/model/Parcels.kt index 1d7a5f9..ee809ad 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/model/Parcels.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/data/remote/model/Parcels.kt @@ -12,7 +12,7 @@ interface DefaultParcelable : Parcelable { override fun describeContents(): Int = 0 companion object { - fun generateCreator(create: (source: Parcel) -> T): Parcelable.Creator = object: Parcelable.Creator { + fun generateCreator(create: (source: Parcel) -> T): Parcelable.Creator = object : Parcelable.Creator { override fun createFromParcel(source: Parcel): T = create(source) override fun newArray(size: Int): Array? = newArray(size) @@ -20,6 +20,7 @@ interface DefaultParcelable : Parcelable { } } + inline fun Parcel.read(): T = readValue(T::class.javaClass.classLoader) as T fun Parcel.write(vararg values: Any?) = values.forEach { writeValue(it) } diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/extensions/ViewExtensions.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/extensions/ViewExtensions.kt index e592095..6bdb699 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/extensions/ViewExtensions.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/extensions/ViewExtensions.kt @@ -4,6 +4,7 @@ import android.content.Context import android.support.annotation.ColorInt import android.support.annotation.StringRes import android.support.design.widget.Snackbar +import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,41 +14,50 @@ import com.squareup.picasso.Picasso var View.isVisible: Boolean get() = visibility == View.VISIBLE set(value) { - visibility = if(value) View.VISIBLE else View.GONE + visibility = if (value) View.VISIBLE else View.GONE } -fun Context.inflateLayout(layoutResId: Int): View { - return inflateView(this, layoutResId, null, false) -} - -fun Context.inflateLayout(layoutResId: Int, parent: ViewGroup): View { - return inflateLayout(layoutResId, parent, true) -} - -fun Context.inflateLayout(layoutResId: Int, parent: ViewGroup, attachToRoot: Boolean): View { - return inflateView(this, layoutResId, parent, attachToRoot) -} - -private fun inflateView(context: Context, layoutResId: Int, parent: ViewGroup?, attachToRoot: Boolean): View { - return LayoutInflater.from(context).inflate(layoutResId, parent, attachToRoot) -} +fun Context.inflateLayout( + layoutResId: Int, + parent: ViewGroup? = null, + attachToRoot: Boolean = parent != null +): View = + LayoutInflater.from(this).inflate(layoutResId, parent, attachToRoot) fun ImageView.loadImage(url: String) { Picasso.with(context).load(url).into(this) } -fun View.showSnackbar(message: String, length: Int = Snackbar.LENGTH_LONG, f: (Snackbar.() -> Unit) = {}) { - val snack = Snackbar.make(this, message, length) - snack.f() - snack.show() +fun View.showSnackbar( + message: String, + length: Int = Snackbar.LENGTH_LONG, + f: (Snackbar.() -> Unit) = {} +) { + Snackbar.make(this, message, length).apply { + f() + show() + } } -fun View.showSnackbar(@StringRes message: Int, length: Int = Snackbar.LENGTH_LONG, f: (Snackbar.() -> Unit) = {}) { +fun View.showSnackbar( + @StringRes message: Int, + length: Int = Snackbar.LENGTH_LONG, + f: (Snackbar.() -> Unit) = {} +) { showSnackbar(resources.getString(message), length, f) } -fun Snackbar.action(action: String, @ColorInt color: Int? = null, listener: (View) -> Unit) { +fun Snackbar.action( + action: String, + @ColorInt color: Int? = null, + listener: (View) -> Unit +) { setAction(action, listener) color?.let { setActionTextColor(color) } } +val RecyclerView.childList: List + get() = (0..childCount - 1).map { getChildAt(it) } + +val View.recyclerParams: RecyclerView.LayoutParams + get() = layoutParams as RecyclerView.LayoutParams diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/AbstractViewModel.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/AbstractViewModel.kt index d9b0171..b247613 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/AbstractViewModel.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/AbstractViewModel.kt @@ -2,7 +2,7 @@ package io.github.plastix.kotlinboilerplate.ui.base import android.databinding.BaseObservable -abstract class AbstractViewModel : BaseObservable(), ViewModel { +abstract class AbstractViewModel : BaseObservable(), ViewModel { override fun bind() { } diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/BaseActivity.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/BaseActivity.kt index af87865..25f2c6e 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/BaseActivity.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/BaseActivity.kt @@ -1,16 +1,18 @@ package io.github.plastix.kotlinboilerplate.ui.base +import activitystarter.ActivityStarter import android.os.Bundle import android.support.annotation.CallSuper import android.support.v7.app.AppCompatActivity import io.github.plastix.kotlinboilerplate.ApplicationComponent import io.github.plastix.kotlinboilerplate.KotlinBoilerplateApp -abstract class BaseActivity: AppCompatActivity() { +abstract class BaseActivity : AppCompatActivity() { @CallSuper - override fun onCreate(savedInstanceState: Bundle?){ + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + ActivityStarter.fill(this) injectDependencies(KotlinBoilerplateApp.graph) } diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModel.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModel.kt index bbdebc4..089fae2 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModel.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModel.kt @@ -1,6 +1,7 @@ package io.github.plastix.kotlinboilerplate.ui.base -interface ViewModel { +interface +ViewModel { fun bind() diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModelLoader.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModelLoader.kt index 54d466f..975db3c 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModelLoader.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/base/ViewModelLoader.kt @@ -31,7 +31,6 @@ class ViewModelLoader @Inject constructor( override fun onReset() { super.onReset() - viewModel?.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/detail/DetailActivity.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/detail/DetailActivity.kt index 930bb6c..db4bfe6 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/detail/DetailActivity.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/detail/DetailActivity.kt @@ -1,7 +1,6 @@ package io.github.plastix.kotlinboilerplate.ui.detail -import android.content.Context -import android.content.Intent +import activitystarter.Arg import android.databinding.DataBindingUtil import android.os.Bundle import io.github.plastix.kotlinboilerplate.ApplicationComponent @@ -13,17 +12,7 @@ import io.github.plastix.kotlinboilerplate.ui.base.ViewModelActivity open class DetailActivity : ViewModelActivity() { - companion object { - val EXTRA_REPO_OBJECT = "REPO_ITEM" - - fun newIntent(context: Context, repo: Repo): Intent { - val intent = Intent(context, DetailActivity::class.java) - intent.putExtra(EXTRA_REPO_OBJECT, repo) - return intent - } - } - - private val repo by lazy { intent.getParcelableExtra(EXTRA_REPO_OBJECT) } + @Arg lateinit var repo: Repo override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -36,9 +25,8 @@ open class DetailActivity : ViewModelActivity() { @Inject - lateinit var adapter: RepoAdapter + lateinit var listAdapter: RepoAdapter @Inject - lateinit var layoutManager: LinearLayoutManager + lateinit var listLayoutManager: LinearLayoutManager @Inject lateinit var dividerDecorator: SimpleDividerItemDecoration @@ -43,27 +43,10 @@ class ListActivity : ViewModelActivity() { setupRecyclerView() setupSwipeRefresh() updateEmptyView() - - disposables.add(viewModel.getRepos().subscribe { - updateList(it) - }) - - disposables.add(viewModel.loadingState().subscribe { - binding.listSwipeRefresh.isRefreshing = it - }) - - disposables.add(viewModel.fetchErrors().subscribe { - errorFetchRepos() - }) - - disposables.add(viewModel.networkErrors().subscribe { - errorNoNetwork() - }) + addDisposables() } - override fun getViewBinding(): ActivityListBinding { - return DataBindingUtil.setContentView(this, R.layout.activity_list) - } + override fun getViewBinding(): ActivityListBinding = DataBindingUtil.setContentView(this, R.layout.activity_list) private fun setupSwipeRefresh() { binding.listSwipeRefresh.setOnRefreshListener { @@ -72,13 +55,12 @@ class ListActivity : ViewModelActivity() { } private fun setupRecyclerView() { - binding.listRecyclerView.adapter = adapter - binding.listRecyclerView.layoutManager = layoutManager - binding.listRecyclerView.addItemDecoration(dividerDecorator) - - adapter.setClickListener { - onItemClick(it) + binding.listRecyclerView.apply { + adapter = listAdapter + layoutManager = listLayoutManager + addItemDecoration(dividerDecorator) } + listAdapter.setClickListener(this::onItemClick) } override fun injectDependencies(graph: ApplicationComponent) { @@ -93,19 +75,39 @@ class ListActivity : ViewModelActivity() { } private fun onItemClick(repo: Repo) { - startActivity(DetailActivity.newIntent(this, repo)) + DetailActivityStarter.start(this, repo) } private fun updateList(repos: List) { - adapter.updateRepos(repos) + listAdapter.updateRepos(repos) updateEmptyView() } private fun updateEmptyView() { - val thereIsNoItems = adapter.itemCount == 0 + val thereIsNoItems = listAdapter.itemCount == 0 binding.emptyView.root.isVisible = thereIsNoItems } + private fun addDisposables() { + disposables.apply { + add(viewModel.getRepos().subscribe { + updateList(it) + }) + + add(viewModel.loadingState().subscribe { + binding.listSwipeRefresh.isRefreshing = it + }) + + add(viewModel.fetchErrors().subscribe { + errorFetchRepos() + }) + + add(viewModel.networkErrors().subscribe { + errorNoNetwork() + }) + } + } + private fun errorNoNetwork() { binding.listCoordinatorLayout.showSnackbar(R.string.list_error_no_network) } @@ -119,29 +121,24 @@ class ListActivity : ViewModelActivity() { disposables.clear() } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - // Handle action bar item clicks here. The action bar will - // automatically handle clicks on the Home/Up button, so long - // as you specify a parent activity in AndroidManifest.xml. - return when (item.itemId) { - R.id.action_settings -> { - Timber.d("Settings menu clicked!") - true - } - - R.id.action_night -> { - AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) - recreate() - true - } - - R.id.action_day -> { - AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) - recreate() - true - } - - else -> super.onOptionsItemSelected(item) + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) { + R.id.action_settings -> { + Timber.d("Settings menu clicked!") + true + } + R.id.action_night -> { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) + recreate() + true + } + R.id.action_day -> { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) + recreate() + true } + else -> super.onOptionsItemSelected(item) } } diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt index c98da82..5f8af4a 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt @@ -8,6 +8,7 @@ import io.github.plastix.kotlinboilerplate.data.remote.model.SearchResponse import io.github.plastix.kotlinboilerplate.ui.base.RxViewModel import io.github.plastix.rxdelay.RxDelay import io.reactivex.Observable +import io.reactivex.Single import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposables @@ -18,7 +19,7 @@ import io.reactivex.subjects.PublishSubject import javax.inject.Inject class ListViewModel @Inject constructor( - private val apiService: GithubApiService, + apiService: GithubApiService, private val networkInteractor: NetworkInteractor ) : RxViewModel() { @@ -29,28 +30,19 @@ class ListViewModel @Inject constructor( private val fetchErrors: PublishSubject = PublishSubject.create() private val networkErrors: PublishSubject = PublishSubject.create() + val repoSearch = apiService.repoSearch(ApiConstants.SEARCH_QUERY_KOTLIN, + ApiConstants.SEARCH_SORT_STARS, + ApiConstants.SEARCH_ORDER_DESCENDING) + fun fetchRepos() { - networkRequest = networkInteractor.hasNetworkConnectionCompletable() - .andThen(apiService.repoSearch(ApiConstants.SEARCH_QUERY_KOTLIN, - ApiConstants.SEARCH_SORT_STARS, - ApiConstants.SEARCH_ORDER_DESCENDING)) - .subscribeOn(Schedulers.io()) - .compose(RxDelay.delaySingle(getViewState())) - .observeOn(AndroidSchedulers.mainThread()) - .doOnSubscribe { - networkRequest.dispose() // Cancel any current running request - loadingState.onNext(true) - } - .doOnEvent { searchResponse, throwable -> - loadingState.onNext(false) - } + networkRequest = networkInteractor + .hasNetworkConnectionCompletable() + .andThen(repoSearch) + .applySchedulers(getViewState()) + .addOnResultEvents() .subscribeWith(object : DisposableSingleObserver() { override fun onError(e: Throwable) { - System.out.println(e.toString()) - when (e) { - is NetworkInteractor.NetworkUnavailableException -> networkErrors.onNext(e) - else -> fetchErrors.onNext(e) - } + onRequestError(e) } override fun onSuccess(value: SearchResponse) { @@ -69,4 +61,26 @@ class ListViewModel @Inject constructor( fun loadingState(): Observable = loadingState.hide() + private fun Single.applySchedulers(viewState: Observable) = this + .subscribeOn(Schedulers.io()) + .compose(RxDelay.delaySingle(viewState)) + .observeOn(AndroidSchedulers.mainThread()) + + private fun Single.addOnResultEvents() = this + .doOnSubscribe { + networkRequest.dispose() // Cancel any current running request + loadingState.onNext(true) + } + .doOnEvent { _, _ -> + loadingState.onNext(false) + } + + private fun onRequestError(e: Throwable) { + System.out.println(e.toString()) + when (e) { + is NetworkInteractor.NetworkUnavailableException -> networkErrors.onNext(e) + else -> fetchErrors.onNext(e) + } + } + } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/RepoAdapter.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/RepoAdapter.kt index f9633e4..3cc7fd4 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/RepoAdapter.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/RepoAdapter.kt @@ -60,7 +60,7 @@ class RepoAdapter @Inject constructor() : RecyclerView.Adapter Unit)?){ + fun setClickListener(callback: ((Repo) -> Unit)?) { binding.viewModel.clicks().subscribe { callback?.invoke(binding.viewModel.repo) } diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/RepoDiffCallback.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/RepoDiffCallback.kt index a364e5f..66656e0 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/RepoDiffCallback.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/RepoDiffCallback.kt @@ -5,19 +5,13 @@ import io.github.plastix.kotlinboilerplate.data.remote.model.Repo class RepoDiffCallback(private val old: List, private val new: List) : DiffUtil.Callback() { - override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { - return old[oldItemPosition].fullName == new[newItemPosition].fullName - } + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = + old[oldItemPosition].fullName == new[newItemPosition].fullName - override fun getOldListSize(): Int { - return old.size - } + override fun getOldListSize() = old.size - override fun getNewListSize(): Int { - return new.size - } + override fun getNewListSize() = new.size - override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { - return old[oldItemPosition] == new[newItemPosition] - } + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = + old[oldItemPosition] == new[newItemPosition] } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/misc/SimpleDividerItemDecoration.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/misc/SimpleDividerItemDecoration.kt index 371b4dc..5a40ada 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/misc/SimpleDividerItemDecoration.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/misc/SimpleDividerItemDecoration.kt @@ -7,6 +7,8 @@ import android.support.v4.content.ContextCompat import android.support.v7.widget.RecyclerView import io.github.plastix.kotlinboilerplate.ApplicationQualifier import io.github.plastix.kotlinboilerplate.R +import io.github.plastix.kotlinboilerplate.extensions.childList +import io.github.plastix.kotlinboilerplate.extensions.recyclerParams import javax.inject.Inject /** @@ -24,17 +26,16 @@ class SimpleDividerItemDecoration @Inject constructor( val left = parent.paddingLeft val right = parent.width - parent.paddingRight - val childCount = parent.childCount - for (i in 0..childCount - 1) { - val child = parent.getChildAt(i) - - val params = child.layoutParams as RecyclerView.LayoutParams - - val top = child.bottom + params.bottomMargin + parent.childList.forEach { child -> + val top = child.bottom + child.recyclerParams.bottomMargin val bottom = top + divider.intrinsicHeight - divider.setBounds(left, top, right, bottom) - divider.draw(c) + drawDivider(c, left, top, right, bottom) } } + + private fun drawDivider(c: Canvas, left: Int, top: Int, right: Int, bottom: Int) { + divider.setBounds(left, top, right, bottom) + divider.draw(c) + } } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 971b1e8..6cbd0e3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Sep 22 18:24:14 EDT 2016 +#Sat Mar 18 12:40:59 CET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip From a093613587fc861a48a5938d2826b1e50d52f0c5 Mon Sep 17 00:00:00 2001 From: MarcinMoskala Date: Sat, 18 Mar 2017 13:08:09 +0100 Subject: [PATCH 4/6] Replace lambdas with member reference --- .../kotlinboilerplate/ui/list/ListActivity.kt | 23 +++++-------------- .../ui/list/ListViewModel.kt | 20 ++++++++-------- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListActivity.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListActivity.kt index a1cd1ad..73258a9 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListActivity.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListActivity.kt @@ -90,29 +90,18 @@ class ListActivity : ViewModelActivity() { private fun addDisposables() { disposables.apply { - add(viewModel.getRepos().subscribe { - updateList(it) - }) - - add(viewModel.loadingState().subscribe { - binding.listSwipeRefresh.isRefreshing = it - }) - - add(viewModel.fetchErrors().subscribe { - errorFetchRepos() - }) - - add(viewModel.networkErrors().subscribe { - errorNoNetwork() - }) + add(viewModel.getRepos().subscribe(this@ListActivity::updateList)) + add(viewModel.loadingState().subscribe(binding.listSwipeRefresh::setRefreshing)) + add(viewModel.fetchErrors().subscribe(this@ListActivity::errorFetchRepos)) + add(viewModel.networkErrors().subscribe(this@ListActivity::errorNoNetwork)) } } - private fun errorNoNetwork() { + private fun errorNoNetwork(throwable: Throwable) { binding.listCoordinatorLayout.showSnackbar(R.string.list_error_no_network) } - private fun errorFetchRepos() { + private fun errorFetchRepos(throwable: Throwable) { binding.listCoordinatorLayout.showSnackbar(R.string.list_error_failed_fetch) } diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt index 5f8af4a..cdeee6f 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt @@ -30,9 +30,11 @@ class ListViewModel @Inject constructor( private val fetchErrors: PublishSubject = PublishSubject.create() private val networkErrors: PublishSubject = PublishSubject.create() - val repoSearch = apiService.repoSearch(ApiConstants.SEARCH_QUERY_KOTLIN, + val repoSearch = apiService.repoSearch( + ApiConstants.SEARCH_QUERY_KOTLIN, ApiConstants.SEARCH_SORT_STARS, - ApiConstants.SEARCH_ORDER_DESCENDING) + ApiConstants.SEARCH_ORDER_DESCENDING + ) fun fetchRepos() { networkRequest = networkInteractor @@ -40,19 +42,15 @@ class ListViewModel @Inject constructor( .andThen(repoSearch) .applySchedulers(getViewState()) .addOnResultEvents() - .subscribeWith(object : DisposableSingleObserver() { - override fun onError(e: Throwable) { - onRequestError(e) - } - - override fun onSuccess(value: SearchResponse) { - repos.onNext(value.repos) - } - }) + .subscribe(this::onRequestSuccess, this::onRequestError) addDisposable(networkRequest) } + fun onRequestSuccess(value: SearchResponse) { + repos.onNext(value.repos) + } + fun getRepos(): Observable> = repos.hide() fun fetchErrors(): Observable = fetchErrors.hide() From 97552bba202b16912d02dae9000e99094724fb20 Mon Sep 17 00:00:00 2001 From: MarcinMoskala Date: Sat, 18 Mar 2017 13:15:35 +0100 Subject: [PATCH 5/6] Fix + Clean-up in tests --- .../kotlinboilerplate/ui/list/ListViewModel.kt | 4 ++-- .../ui/detail/DetailViewModelTest.kt | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt index cdeee6f..7e1a3f4 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt @@ -19,7 +19,7 @@ import io.reactivex.subjects.PublishSubject import javax.inject.Inject class ListViewModel @Inject constructor( - apiService: GithubApiService, + private val apiService: GithubApiService, private val networkInteractor: NetworkInteractor ) : RxViewModel() { @@ -30,7 +30,7 @@ class ListViewModel @Inject constructor( private val fetchErrors: PublishSubject = PublishSubject.create() private val networkErrors: PublishSubject = PublishSubject.create() - val repoSearch = apiService.repoSearch( + val repoSearch get() = apiService.repoSearch( ApiConstants.SEARCH_QUERY_KOTLIN, ApiConstants.SEARCH_SORT_STARS, ApiConstants.SEARCH_ORDER_DESCENDING diff --git a/app/src/unitTests/kotlin/io/github/plastix/kotlinboilerplate/ui/detail/DetailViewModelTest.kt b/app/src/unitTests/kotlin/io/github/plastix/kotlinboilerplate/ui/detail/DetailViewModelTest.kt index a6771b4..4b32ee3 100644 --- a/app/src/unitTests/kotlin/io/github/plastix/kotlinboilerplate/ui/detail/DetailViewModelTest.kt +++ b/app/src/unitTests/kotlin/io/github/plastix/kotlinboilerplate/ui/detail/DetailViewModelTest.kt @@ -14,15 +14,19 @@ class DetailViewModelTest { @Before fun setUp() { - owner = Owner("Author", - "someURL") + owner = Owner( + "Author", + "someURL" + ) - repo = Repo("Name", + repo = Repo( + "Name", "Author/Name", owner, "Some random repo", 50, - 100) + 100 + ) viewModel = DetailViewModel(repo) viewModel.bind() From 1d1213b00d2fddc4f35ac61321e078da97ef392f Mon Sep 17 00:00:00 2001 From: MarcinMoskala Date: Sat, 18 Mar 2017 13:20:19 +0100 Subject: [PATCH 6/6] Code clean-up according to Kotlin coding conventions --- .../kotlinboilerplate/ui/list/ListViewModel.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt index 7e1a3f4..10cfd19 100644 --- a/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt +++ b/app/src/main/kotlin/io/github/plastix/kotlinboilerplate/ui/list/ListViewModel.kt @@ -30,16 +30,10 @@ class ListViewModel @Inject constructor( private val fetchErrors: PublishSubject = PublishSubject.create() private val networkErrors: PublishSubject = PublishSubject.create() - val repoSearch get() = apiService.repoSearch( - ApiConstants.SEARCH_QUERY_KOTLIN, - ApiConstants.SEARCH_SORT_STARS, - ApiConstants.SEARCH_ORDER_DESCENDING - ) - fun fetchRepos() { networkRequest = networkInteractor .hasNetworkConnectionCompletable() - .andThen(repoSearch) + .andThen(getRepoSearch()) .applySchedulers(getViewState()) .addOnResultEvents() .subscribe(this::onRequestSuccess, this::onRequestError) @@ -47,6 +41,12 @@ class ListViewModel @Inject constructor( addDisposable(networkRequest) } + private fun getRepoSearch() = apiService.repoSearch( + ApiConstants.SEARCH_QUERY_KOTLIN, + ApiConstants.SEARCH_SORT_STARS, + ApiConstants.SEARCH_ORDER_DESCENDING + ) + fun onRequestSuccess(value: SearchResponse) { repos.onNext(value.repos) }