-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
*.iml | ||
.gradle | ||
/local.properties | ||
/.idea/caches | ||
/.idea/libraries | ||
/.idea/modules.xml | ||
/.idea/workspace.xml | ||
/.idea/navEditor.xml | ||
/.idea/assetWizardSettings.xml | ||
.DS_Store | ||
/build | ||
/captures | ||
.externalNativeBuild |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
apply plugin: 'com.android.application' | ||
|
||
apply plugin: 'kotlin-android' | ||
|
||
apply plugin: 'kotlin-android-extensions' | ||
|
||
android { | ||
compileSdkVersion 27 | ||
defaultConfig { | ||
applicationId "com.cars" | ||
minSdkVersion 16 | ||
targetSdkVersion 27 | ||
versionCode 1 | ||
versionName "1.0" | ||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | ||
} | ||
buildTypes { | ||
release { | ||
minifyEnabled false | ||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | ||
} | ||
} | ||
testOptions { | ||
unitTests.returnDefaultValues = true | ||
} | ||
} | ||
|
||
dependencies { | ||
implementation fileTree(dir: 'libs', include: ['*.jar']) | ||
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" | ||
implementation 'com.android.support:appcompat-v7:27.1.1' | ||
implementation 'com.android.support:recyclerview-v7:27.1.1' | ||
testImplementation 'junit:junit:4.12' | ||
testImplementation 'org.json:json:20180130' | ||
testImplementation 'org.assertj:assertj-core:3.11.1' | ||
testImplementation 'org.mockito:mockito-core:2.23.0' | ||
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0" | ||
androidTestImplementation 'com.android.support.test:runner:1.0.2' | ||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' | ||
|
||
implementation "io.reactivex.rxjava2:rxandroid:2.1.1" | ||
implementation "io.reactivex.rxjava2:rxjava:2.2.8" | ||
implementation "com.squareup.okhttp3:okhttp:3.12.1" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Add project specific ProGuard rules here. | ||
# You can control the set of applied configuration files using the | ||
# proguardFiles setting in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} | ||
|
||
# Uncomment this to preserve the line number information for | ||
# debugging stack traces. | ||
#-keepattributes SourceFile,LineNumberTable | ||
|
||
# If you keep the line number information, uncomment this to | ||
# hide the original source file name. | ||
#-renamesourcefileattribute SourceFile |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="com.cars"> | ||
|
||
<uses-permission android:name="android.permission.INTERNET"/> | ||
|
||
<application | ||
android:icon="@mipmap/ic_launcher" | ||
android:label="@string/app_name" | ||
android:roundIcon="@mipmap/ic_launcher_round" | ||
android:supportsRtl="true" | ||
android:theme="@style/AppTheme"> | ||
<activity android:name=".MainActivity" | ||
android:launchMode="singleTask"> | ||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN"/> | ||
|
||
<category android:name="android.intent.category.LAUNCHER"/> | ||
</intent-filter> | ||
</activity> | ||
</application> | ||
|
||
</manifest> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.cars | ||
|
||
import android.content.Context | ||
import com.cars.model.DataModel | ||
|
||
interface Contract { | ||
interface Presenter<T> { | ||
fun reload() | ||
fun loadNext() | ||
fun canLoadMore(): Boolean | ||
fun isLoading(): Boolean | ||
fun getDataSet(): List<T> | ||
|
||
fun onCreate() | ||
fun onDestroy() | ||
fun onViewCreated(view: View<T>) | ||
fun onDestroyView() | ||
|
||
fun onItemClicked(context: Context, item: DataModel) | ||
} | ||
|
||
interface View<T> { | ||
fun updateGlobalLoader(loading: Boolean) | ||
fun updatePageLoader(loading: Boolean) | ||
fun onError(throwable: Throwable) | ||
fun onNewDataSet() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package com.cars | ||
|
||
import android.content.Intent | ||
import android.os.Bundle | ||
import android.support.v7.app.AppCompatActivity | ||
import android.view.MenuItem | ||
import com.cars.view.CarFragment | ||
import com.cars.view.ManufacturerFragment | ||
import com.cars.view.ModelFragment | ||
import com.cars.view.YearFragment | ||
|
||
class MainActivity : AppCompatActivity() { | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
supportActionBar?.setDisplayHomeAsUpEnabled(true) | ||
setContentView(R.layout.activity_main) | ||
if (savedInstanceState == null) { | ||
supportFragmentManager | ||
.beginTransaction() | ||
.replace(R.id.content_view, ManufacturerFragment()) | ||
.commit() | ||
} | ||
} | ||
|
||
override fun onOptionsItemSelected(item: MenuItem): Boolean { | ||
if (item.itemId == android.R.id.home) { | ||
if (supportFragmentManager.backStackEntryCount > 0) { | ||
supportFragmentManager.popBackStack() | ||
} else { | ||
super.onBackPressed() | ||
} | ||
} | ||
return true | ||
} | ||
|
||
override fun onNewIntent(intent: Intent?) { | ||
super.onNewIntent(intent) | ||
intent?.apply { | ||
val fragment = when (getIntExtra(FRAGMENT, 0)) { | ||
MODEL_FRAGMENT -> ModelFragment() | ||
YEAR_FRAGMENT -> YearFragment() | ||
CAR_FRAGMENT -> CarFragment() | ||
else -> return | ||
} | ||
|
||
getBundleExtra(DATA_BUNDLE)?.let { data -> | ||
fragment.arguments = data | ||
supportFragmentManager | ||
.beginTransaction() | ||
.setCustomAnimations( | ||
R.animator.right_in, R.animator.right_out, | ||
R.animator.left_in, R.animator.left_out | ||
) | ||
.replace(R.id.content_view, fragment) | ||
.addToBackStack(null) | ||
.commit() | ||
} | ||
} | ||
} | ||
|
||
companion object { | ||
const val DATA_BUNDLE = "data" | ||
const val FRAGMENT = "fragment" | ||
const val MODEL_FRAGMENT = 100 | ||
const val YEAR_FRAGMENT = 101 | ||
const val CAR_FRAGMENT = 102 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package com.cars.adapter | ||
|
||
import android.support.v7.widget.RecyclerView | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import com.cars.R | ||
import com.cars.holder.CarsItemViewHolder | ||
import com.cars.holder.ProgressItemViewHolder | ||
import com.cars.model.DataModel | ||
|
||
class Adapter<T: DataModel>(private val clickListener: View.OnClickListener) | ||
: RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||
|
||
val dataSet = ArrayList<T>() | ||
private var loadingMode = false | ||
|
||
fun setLoadingMode(loading: Boolean) { | ||
if (loadingMode != loading) { | ||
loadingMode = loading | ||
notifyItemChanged(itemCount) | ||
} | ||
} | ||
|
||
override fun getItemViewType(position: Int): Int { | ||
return if (loadingMode && position == itemCount - 1) VIEW_TYPE_PROGRESS | ||
else if (position % 2 == 0) VIEW_TYPE_EVEN else VIEW_TYPE_ODD | ||
} | ||
|
||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { | ||
return when (viewType) { | ||
VIEW_TYPE_ODD -> CarsItemViewHolder(parent, clickListener, R.color.cars_view_item_background_transparent) | ||
VIEW_TYPE_EVEN -> CarsItemViewHolder(parent, clickListener, R.color.cars_view_item_background_colored) | ||
else -> ProgressItemViewHolder(parent) | ||
} | ||
} | ||
|
||
override fun getItemCount(): Int = dataSet.size + (if (loadingMode) 1 else 0) | ||
|
||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { | ||
when (holder.itemViewType) { | ||
VIEW_TYPE_ODD, | ||
VIEW_TYPE_EVEN -> (holder as CarsItemViewHolder).bind(dataSet[position]) | ||
else -> {} | ||
} | ||
} | ||
|
||
companion object { | ||
const val VIEW_TYPE_PROGRESS = 0 | ||
const val VIEW_TYPE_ODD = 1 | ||
const val VIEW_TYPE_EVEN = 2 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.cars.adapter | ||
|
||
import android.support.v7.util.DiffUtil | ||
import com.cars.model.DataModel | ||
|
||
class DataDiffUtilCallback(private val old: List<DataModel>, | ||
private val new: List<DataModel>) : DiffUtil.Callback() { | ||
|
||
override fun getOldListSize(): Int = old.size | ||
|
||
override fun getNewListSize(): Int = new.size | ||
|
||
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { | ||
return old[oldItemPosition].getDataId() == new[newItemPosition].getDataId() | ||
} | ||
|
||
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { | ||
return old[oldItemPosition].getDisplayData() == new[newItemPosition].getDisplayData() | ||
} | ||
} |