Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stream Episode 17: Initial SharedPreferences storage implementation #81

Merged
merged 19 commits into from
Oct 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

<a alt='Watch the Stream' href='https://twitch.tv/joaquimley' target='_blank' align='left'><img align='right' height='50' style='border:0px;height:50px;' src='art/follow_me_twitch_badge.png?v=0' border='0' /></a>

<a alt='Available soon' href='' target='_blank' align='left'><img align='right' height='36' style='border:0px;height:36px;' src='art/googleplay_soon.png?v=0' border='0' /></a>
<a alt='Available soon' align='left'><img align='right' height='36' style='border:0px;height:36px;' src='art/googleplay_soon.png?v=0' border='0' /></a>

# Transport ETA
[![License Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=true)](http://www.apache.org/licenses/LICENSE-2.0)

![production version](https://img.shields.io/badge/playstore-unreleased-lightgrey.svg?style=true)
![minSdkVersion 19](https://img.shields.io/badge/minSdkVersion-19-yellow.svg?style=true)
![compileSdkVersion 27](https://img.shields.io/badge/compileSdkVersion-28-green.svg?style=true)
![compileSdkVersion 28](https://img.shields.io/badge/compileSdkVersion-28-green.svg?style=true)
[![Build Status](https://app.bitrise.io/app/f75916759d698e6e/status.svg?token=nCaNQBZcMNPMckWWwn8Gxg&branch=develop)](https://app.bitrise.io/app/f75916759d698e6e)
[![codecov](https://codecov.io/gh/JoaquimLey/transport-eta/branch/develop/graph/badge.svg)](https://codecov.io/gh/JoaquimLey/transport-eta)

Expand All @@ -28,8 +29,8 @@ An utility app using an SMS based service (or the web) to request a more precise
## Why 🤔
Since I'm always working on some side-projects, I decided to document the progress live on a coding stream, this way I'll force myself into completing, while giving something back to a community that already thought me so much.

## Stream log
##### Come and say Hi 👋, join me at [twitch.tv/joaquimley](http:twitch.tv/joaquimley): watch, help, and learn as I develop and make mistakes
## Stream PR log
##### Come and say Hi 👋 and be part of the develpoment live at [twitch.tv/joaquimley](http:twitch.tv/joaquimley)

- Ep.1: https://github.com/JoaquimLey/transport-eta/tree/4642c5fd6af9de3b258b179d0a7a8c69195fa293

Expand Down Expand Up @@ -61,7 +62,9 @@ Since I'm always working on some side-projects, I decided to document the progre

- Ep.15: https://github.com/JoaquimLey/transport-eta/pull/70

- Ep.15: https://github.com/JoaquimLey/transport-eta/pull/74
- Ep.16: https://github.com/JoaquimLey/transport-eta/pull/74

- Ep.17: https://github.com/JoaquimLey/transport-eta/pull/81


## About the author
Expand Down Expand Up @@ -92,7 +95,7 @@ Personal website:

#### Important references

It would take substantially more time to setup this project without this reference projects
It would take substantially more time to setup this project without this reference projects, so a special thanks to:

- https://github.com/bufferapp/clean-architecture-components-boilerplate

Expand Down
4 changes: 1 addition & 3 deletions transport-eta-android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ buildscript {
addRepos(repositories)
dependencies {
classpath deps.kotlin.plugin
classpath deps.kotlin.serialization_plugin
classpath deps.navigation.safe_args
classpath deps.android_gradle_plugin
}
repositories {
google()
}
}

allprojects {
Expand Down
10 changes: 10 additions & 0 deletions transport-eta-android/data-sharedpreferences/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlinx-serialization'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

Expand All @@ -11,6 +12,12 @@ android {
testInstrumentationRunner "com.joaquimley.transporteta.ui.test.TestRunner"
}

testOptions {
unitTests {
includeAndroidResources = true
}
}

packagingOptions {
exclude 'LICENSE.txt'
exclude 'META-INF/DEPENDENCIES'
Expand Down Expand Up @@ -90,6 +97,7 @@ dependencies {
implementation deps.rx.android
// Kotlin
implementation deps.kotlin.rx
implementation deps.kotlin.serialization
implementation deps.kotlin.stdlib

/***********
Expand All @@ -102,6 +110,8 @@ dependencies {
testImplementation deps.mockito.kotlin
testImplementation deps.mockito.inline
testImplementation deps.lifecycle.testing
testImplementation deps.robolectric

// Resolve conflicts between main and local unit tests
testImplementation deps.androidx.annotation
}
17 changes: 10 additions & 7 deletions transport-eta-android/data-sharedpreferences/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@
# 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

-keepattributes *Annotation*, InnerClasses
-dontnote kotlinx.serialization.SerializationKt
-keep,includedescriptorclasses class com.yourcompany.yourpackage.**$$serializer { *; } # <-- change package name to your app's
-keepclassmembers class com.yourcompany.yourpackage.** { # <-- change package name to your app's
*** Companion;
}
-keepclasseswithmembers class com.yourcompany.yourpackage.** { # <-- change package name to your app's
kotlinx.serialization.KSerializer serializer(...);
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,91 @@
package com.joaquimley.transporteta.sharedpreferences

import android.content.SharedPreferences
import com.joaquimley.transporteta.data.model.TransportEntity
import com.joaquimley.transporteta.data.source.FrameworkLocalStorage
import com.joaquimley.transporteta.sharedpreferences.mapper.SharedPrefTransportMapper
import com.joaquimley.transporteta.sharedpreferences.model.SharedPrefTransport
import io.reactivex.Completable
import io.reactivex.Single
import io.reactivex.subjects.PublishSubject
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class FrameworkLocalStorageImpl @Inject constructor(private val sharedPreferences: SharedPreferences,
private val mapper: SharedPrefTransportMapper) : FrameworkLocalStorage {

private val sharedPreferencesObservable: PublishSubject<List<TransportEntity>> = PublishSubject.create()

init {
loadAll()
observeSharedPreferencesChanges()
}

class FrameworkLocalStorageImpl: FrameworkLocalStorage {
override fun saveTransport(transportEntity: TransportEntity): Completable {
return Completable.complete()
return Completable.fromAction {
saveToSharedPrefs(mapper.toSharedPref(transportEntity))
}
}

override fun deleteTransport(transportEntityId: String): Completable {
return Completable.complete()
}

override fun getTransport(transportEntityId: String): Single<TransportEntity> {
return Single.just(TransportEntity("hi", "mock",2, "el", true,"bus"))
return Single.just(TransportEntity("hi", "mock", 2, "el", true, "bus"))
}

override fun getAll(): Single<List<TransportEntity>> {
val list = mutableListOf<TransportEntity>()
list.add(TransportEntity("hi", "mock",2, "latestEta 12324", true,"bus"))
list.add(TransportEntity("there", "mock",23, "latestEta 123", true,"bus"))
list.add(TransportEntity("hi", "mock", 2, "latestEta 12324", true, "bus"))
list.add(TransportEntity("there", "mock", 23, "latestEta 123", true, "bus"))
list.add(TransportEntity("world", "mock", 25, "latestEta 12454", true, "bus"))
list.add(TransportEntity("sup", "mock", 29, "latestEta 675", true, "bus"))
return Single.just(list)
}

override fun clearAll(): Completable {
return Completable.complete()
return Completable.fromAction {

}
}

private fun observeSharedPreferencesChanges() {
sharedPreferences.registerOnSharedPreferenceChangeListener { _, key ->
if (key != SHARED_PREFERENCES_LAST_UPDATED) {
loadAll()
}
}
}

private fun loadAll() {
val data = mutableListOf<TransportEntity>()
getFromSharedPrefs(Slot.ONE)?.let { data.add(mapper.toEntity(it)) }
getFromSharedPrefs(Slot.TWO)?.let { data.add(mapper.toEntity(it)) }
getFromSharedPrefs(Slot.THREE)?.let { data.add(mapper.toEntity(it)) }
sharedPreferencesObservable.onNext(data)
}

private fun saveToSharedPrefs(sharedPrefTransport: SharedPrefTransport) {
sharedPreferences.edit()
.putString(Slot.ONE.name, mapper.toCacheString(sharedPrefTransport))
.apply()
}

private fun getFromSharedPrefs(slot: Slot): SharedPrefTransport? {
sharedPreferences.getString(slot.name, null)?.let {
return mapper.fromCacheString(it)
} ?: return null
}

companion object {
private const val SHARED_PREFERENCES_LAST_UPDATED = "sharedpreferences.last_updated"
}

enum class Slot(name: String) {
ONE("transport_eta_fav_1"),
TWO("transport_eta_fav_2"),
THREE("transport_eta_fav_3"),
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.joaquimley.transporteta.sharedpreferences.mapper

import com.joaquimley.transporteta.data.model.TransportEntity
import com.joaquimley.transporteta.sharedpreferences.model.SharedPrefTransport
import kotlinx.serialization.json.JSON

class SharedPrefTransportMapper {

fun toCacheString(from: SharedPrefTransport): String {
return JSON.stringify(from)
}

fun fromCacheString(from: String): SharedPrefTransport {
return JSON.parse(from)
}

fun toSharedPref(from: List<TransportEntity>): List<SharedPrefTransport> {
return from.map { toSharedPref(it) }
}

fun toSharedPref(from: TransportEntity): SharedPrefTransport {
return SharedPrefTransport(from.id, from.name, from.code, from.latestEta, from.isFavorite, from.type, 1312, "")
}

fun toEntity(from: List<SharedPrefTransport>): List<TransportEntity> {
return from.map { toEntity(it) }
}

fun toEntity(from: SharedPrefTransport): TransportEntity {
return TransportEntity(from.id, from.name, from.code, from.latestEta, from.isFavorite, from.type)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.joaquimley.transporteta.sharedpreferences.model

class SharedPrefTransport {

// TODO
}
@kotlinx.serialization.Serializable
data class SharedPrefTransport(val id: String, val name: String, val code: Int, val latestEta: String,
val isFavorite: Boolean = false, val type: String, val lastUpdated: Long,
val slot: String)

This file was deleted.

Loading