Skip to content

Commit

Permalink
arch components + dagger updates
Browse files Browse the repository at this point in the history
  • Loading branch information
John O'Reilly committed Nov 26, 2017
1 parent 1f358e2 commit 1ddb385
Show file tree
Hide file tree
Showing 54 changed files with 1,098 additions and 283 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
**/*/res/values/secrets.xml
.gradle
.idea
/local.properties
*iml
*.iml
*/build
build/
.DS_Store


9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
Android Galway Bus app
### Android Galway Bus app using Clean Architecture/Architecture Components/Kotlin/Dagger


Heavily based on https://github.com/bufferapp/clean-architecture-components-boilerplate. This is stil work in progress and also, at least for now,
have omitted `Mapper` classes (using same data model across the different layers....though this will likely change).

Note also that this is using REST endpoint provided by @appsandwich (Thanks Vinny!)

90 changes: 48 additions & 42 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.google.firebase.firebase-crash'
apply plugin: 'com.google.firebase.firebase-perf'
apply plugin: 'kotlin-kapt'


android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
compileSdkVersion project.compileSdkVersion
buildToolsVersion project.buildToolsVersion
defaultConfig {
applicationId "com.surrus.galwaybus"
minSdkVersion 19
targetSdkVersion 26
minSdkVersion project.minSdkVersion
targetSdkVersion project.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
Expand All @@ -28,61 +27,68 @@ android {

}

ext {
JUNIT_VERSION = '4.12'
DAGGER_VERSION = '2.11'
SUPPORT_VERSION = "26.0.0-beta2"
PLAY_SERVICES_VERSION = '11.0.2'
kapt {
correctErrorTypes = true
}



dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestImplementation ('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})

implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation "com.android.support:appcompat-v7:$SUPPORT_VERSION"
testImplementation "junit:junit:$JUNIT_VERSION"
testCompile "org.robolectric:robolectric:3.3"
testCompile "org.robolectric:shadows-multidex:3.1.4"
testCompile "org.robolectric:shadows-play-services:3.1.4"
testCompile "org.mockito:mockito-core:2.2.17"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:${kotlin_version}"
implementation "com.android.support:appcompat-v7:${supportLibVersion}"
testImplementation "junit:junit:${junitVersion}"
testImplementation "org.robolectric:robolectric:${robolectricVersion}"
//testImplementation "org.robolectric:shadows-multidex:3.1.4"
//testImplementation "org.robolectric:shadows-play-services:3.1.4"
testImplementation "org.mockito:mockito-core:${mockitoAndroidVersion}"
testImplementation "com.nhaarman:mockito-kotlin:${mockitoKotlinVersion}"


implementation "com.google.firebase:firebase-core:${playServicesVersion}"
implementation "com.google.firebase:firebase-auth:${playServicesVersion}"
implementation "com.google.firebase:firebase-database:${playServicesVersion}"
implementation "com.google.firebase:firebase-storage:${playServicesVersion}"
implementation "com.google.firebase:firebase-perf:${playServicesVersion}"
implementation "com.google.firebase:firebase-crash:${playServicesVersion}"
implementation 'com.firebaseui:firebase-ui-auth:3.0.0'

compile "com.google.firebase:firebase-core:$PLAY_SERVICES_VERSION"
compile "com.google.firebase:firebase-auth:$PLAY_SERVICES_VERSION"
compile "com.google.firebase:firebase-database:$PLAY_SERVICES_VERSION"
compile "com.google.firebase:firebase-storage:$PLAY_SERVICES_VERSION"
compile "com.google.firebase:firebase-perf:$PLAY_SERVICES_VERSION"
compile "com.google.firebase:firebase-crash:$PLAY_SERVICES_VERSION"
compile 'com.firebaseui:firebase-ui-auth:2.0.1'
implementation "com.google.android.gms:play-services-maps:${playServicesVersion}"

implementation "com.google.android.gms:play-services-maps:$PLAY_SERVICES_VERSION"
implementation 'com.karumi:dexter:4.1.0'

compile 'com.karumi:dexter:4.1.0'
implementation "io.reactivex.rxjava2:rxjava:${rxJavaVersion}"
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

compile "io.reactivex.rxjava2:rxjava:2.1.1"
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'com.squareup.okhttp3:okhttp:3.8.1'
implementation "com.squareup.retrofit2:retrofit:${retrofitVersion}"
implementation "com.squareup.retrofit2:converter-gson:${retrofitVersion}"
implementation "com.squareup.retrofit2:adapter-rxjava2:${retrofitVersion}"
implementation "com.squareup.retrofit2:converter-scalars:${retrofitVersion}"
implementation "com.google.code.gson:gson:2.6.2"

compile 'com.squareup.okhttp3:okhttp:3.8.1'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
compile "com.squareup.retrofit2:converter-scalars:2.3.0"
compile 'com.google.code.gson:gson:2.6.2'
implementation "android.arch.lifecycle:runtime:${archComponentsVersion}"
implementation "android.arch.lifecycle:extensions:${archComponentsVersion}"
implementation "android.arch.lifecycle:reactivestreams:${archComponentsVersion}"
implementation "android.arch.persistence.room:runtime:${archComponentsVersion}"
annotationProcessor "android.arch.persistence.room:compiler:${archComponentsVersion}"
kapt "android.arch.persistence.room:compiler:${archComponentsVersion}"
implementation "android.arch.persistence.room:rxjava2:${archComponentsVersion}"

implementation "android.arch.lifecycle:runtime:1.0.0-alpha3"
implementation "android.arch.lifecycle:extensions:1.0.0-alpha3"
implementation "android.arch.lifecycle:reactivestreams:1.0.0-alpha3"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0"
testImplementation "android.arch.core:core-testing:1.0.0"

annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha3"

implementation "com.google.dagger:dagger-android:${daggerVersion}"
implementation "com.google.dagger:dagger-android-support:${daggerVersion}"
kapt "com.google.dagger:dagger-compiler:$daggerVersion"
kapt "com.google.dagger:dagger-android-support:${daggerVersion}"
kapt "com.google.dagger:dagger-android-processor:${daggerVersion}"

compile "com.google.dagger:dagger-android:$DAGGER_VERSION"
compile "com.google.dagger:dagger-android-support:$DAGGER_VERSION"
annotationProcessor "com.google.dagger:dagger-android-processor:$DAGGER_VERSION"
}

apply plugin: 'com.google.gms.google-services'

This file was deleted.

10 changes: 2 additions & 8 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,14 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<application
android:name=".GalwayBusApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--
The API key for Google Maps-based APIs is defined as a string resource.
(See the file "res/values/google_maps_api.xml").
Note that the API key is linked to the encryption key used to sign the APK.
You need a different API key for each encryption key, including the release key that is used to
sign the APK for publishing.
You can define the keys for the debug and release targets in src/debug/ and src/release/.
-->

<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
Expand Down
28 changes: 28 additions & 0 deletions app/src/main/java/com/surrus/galwaybus/GalwayBusApplication.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.surrus.galwaybus

import android.app.Activity
import android.app.Application
import com.surrus.galwaybus.di.DaggerApplicationComponent
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasActivityInjector
import javax.inject.Inject

class GalwayBusApplication : Application(), HasActivityInjector {

@Inject lateinit var activityDispatchingAndroidInjector: DispatchingAndroidInjector<Activity>

override fun onCreate() {
super.onCreate()
DaggerApplicationComponent
.builder()
.application(this)
.build()
.inject(this)
}

override fun activityInjector(): AndroidInjector<Activity> {
return activityDispatchingAndroidInjector
}

}
73 changes: 73 additions & 0 deletions app/src/main/java/com/surrus/galwaybus/cache/GalwayBusCacheImpl.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.surrus.galwaybus.cache

import com.surrus.galwaybus.cache.db.GalwayBusDatabase
import com.surrus.galwaybus.data.repository.GalwayBusCache
import com.surrus.galwaybus.model.BusRoute
import io.reactivex.Completable
import io.reactivex.Flowable
import io.reactivex.Single
import javax.inject.Inject

class GalwayBusCacheImpl @Inject constructor(val galwayBusDatabase: GalwayBusDatabase,
private val preferencesHelper: PreferencesHelper) : GalwayBusCache {

private val EXPIRATION_TIME = (60 * 10 * 1000).toLong()


/**
* Retrieve an instance from the database, used for tests.
*/
internal fun getDatabase(): GalwayBusDatabase {
return galwayBusDatabase
}


override fun saveBusRoutes(busRoutes: List<BusRoute>): Completable {
return Completable.defer {
busRoutes.forEach {
galwayBusDatabase.galwayBusDao().insertBusRoute(it)
}
Completable.complete()
}
}

override fun getBusRoutes(): Flowable<List<BusRoute>> {
return Flowable.defer {
Flowable.just(galwayBusDatabase.galwayBusDao().getBusRoutes())
}
}

override fun clearBusRoutes(): Completable {
return Completable.defer {
galwayBusDatabase.galwayBusDao().clearBusRoutes()
Completable.complete()
}
}


override fun isCached(): Single<Boolean> {
return Single.defer {
Single.just(galwayBusDatabase.galwayBusDao().getBusRoutes().isNotEmpty())
}
}

override fun setLastCacheTime(lastCache: Long) {
preferencesHelper.lastCacheTime = lastCache
}

override fun isExpired(): Boolean {
val currentTime = System.currentTimeMillis()
val lastUpdateTime = this.getLastCacheUpdateTimeMillis()
return currentTime - lastUpdateTime > EXPIRATION_TIME
}

/**
* Get in millis, the last time the cache was accessed.
*/
private fun getLastCacheUpdateTimeMillis(): Long {
return preferencesHelper.lastCacheTime
}



}
35 changes: 35 additions & 0 deletions app/src/main/java/com/surrus/galwaybus/cache/PreferenceHelper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.surrus.galwaybus.cache


import android.content.Context
import android.content.SharedPreferences

import javax.inject.Inject
import javax.inject.Singleton

/**
* General Preferences Helper class, used for storing preference values using the Preference API
*/
@Singleton
open class PreferencesHelper @Inject constructor(context: Context) {

companion object {
private val PREF_BUFFER_PACKAGE_NAME = "com.surrus.galwaybus.preferences"

private val PREF_KEY_LAST_CACHE = "last_cache"
}

private val bufferPref: SharedPreferences

init {
bufferPref = context.getSharedPreferences(PREF_BUFFER_PACKAGE_NAME, Context.MODE_PRIVATE)
}

/**
* Store and retrieve the last time data was cached
*/
var lastCacheTime: Long
get() = bufferPref.getLong(PREF_KEY_LAST_CACHE, 0)
set(lastCache) = bufferPref.edit().putLong(PREF_KEY_LAST_CACHE, lastCache).apply()

}
22 changes: 22 additions & 0 deletions app/src/main/java/com/surrus/galwaybus/cache/dao/GalwayBusDao.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.surrus.galwaybus.cache.dao

import android.arch.persistence.room.Dao
import android.arch.persistence.room.Insert
import android.arch.persistence.room.OnConflictStrategy
import android.arch.persistence.room.Query
import com.surrus.galwaybus.cache.db.GalwayBusDatabaseConstants
import com.surrus.galwaybus.model.BusRoute

@Dao
abstract class GalwayBusDao {

@Query(GalwayBusDatabaseConstants.QUERY_BUS_ROUTES)
abstract fun getBusRoutes(): List<BusRoute>

@Query(GalwayBusDatabaseConstants.DELETE_ALL_BUS_ROUTES)
abstract fun clearBusRoutes()

@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract fun insertBusRoute(busRoute: BusRoute)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.surrus.galwaybus.cache.db

import android.arch.persistence.room.Database
import android.arch.persistence.room.RoomDatabase
import com.surrus.galwaybus.cache.dao.GalwayBusDao
import com.surrus.galwaybus.model.BusRoute
import javax.inject.Inject

@Database(entities = arrayOf(BusRoute::class), version = 1)
abstract class GalwayBusDatabase : RoomDatabase() {

abstract fun galwayBusDao(): GalwayBusDao
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.surrus.galwaybus.cache.db

object GalwayBusDatabaseConstants {

const val BUS_ROUTES_TABLE_NAME = "bus_routes"
const val QUERY_BUS_ROUTES = "SELECT * FROM" + " " + BUS_ROUTES_TABLE_NAME
const val DELETE_ALL_BUS_ROUTES = "DELETE FROM" + " " + BUS_ROUTES_TABLE_NAME
}
Loading

0 comments on commit 1ddb385

Please sign in to comment.