Skip to content

Instantly share code, notes, and snippets.

@nglauber
Last active March 5, 2017 16:48
Show Gist options
  • Save nglauber/38f32307c70baa6f4ea6e8665593e231 to your computer and use it in GitHub Desktop.
Save nglauber/38f32307c70baa6f4ea6e8665593e231 to your computer and use it in GitHub Desktop.
apply plugin: 'com.android.application'
apply plugin: "kotlin-android"
android {
...
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
// Dependência da linguagem Kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
// AppCompat
compile "com.android.support:appcompat-v7:$appcompat_version"
// RXJava
compile 'io.reactivex:rxjava:1.2.5'
// RXAndroid para termos acesso a main thread do Android
compile 'io.reactivex:rxandroid:1.2.1'
// Retrofit
compile 'com.squareup.retrofit2:retrofit:2.0.0'
// Adapter do Retrofit para retornar objetos observáveis
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
// Converter do Retrofit para utilizar o Gson para tratar a resposta do servidor
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
// Interceptor para visualizar os logs das requisições do Retrofit
compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
...
}
{
"count": 7,
"next": null,
"previous": null,
"results": [
{
"characters": [
"http://swapi.co/api/people/1/",
...
],
"created": "2014-12-10T14:23:31.880000Z",
"director": "George Lucas",
"edited": "2014-12-12T11:24:39.858000Z",
"episode_id": 4,
"opening_crawl": "It is a period of civil war..",
"planets": [
"http://swapi.co/api/planets/1/",
...
],
"producer": "Gary Kurtz, Rick McCallum",
"release_date": "1977-05-25",
"species": [
"http://swapi.co/api/species/1/",
...
],
"starships": [
"http://swapi.co/api/starships/2/",
...
],
"title": "A New Hope",
"url": "http://swapi.co/api/films/1/",
"vehicles": [
"http://swapi.co/api/vehicles/4/",
...
]
},
// Aqui viriam os demais filmes...
]
}
fun loadMoviesFull(): Observable<Movie> {
return service.listMovies()
.flatMap { filmResults -> Observable.from(filmResults.results) }
.flatMap { film ->
Observable.zip(
Observable.just(Movie(film.title, film.episodeId, ArrayList<Character>())),
Observable.from(film.personUrls)
.flatMap { personUrl ->
service.loadPerson(Uri.parse(personUrl).lastPathSegment)
}
.map { person ->
Character(person!!.name, person.gender)
}
.toList(),
{ movie, characters ->
movie.characters.addAll(characters)
movie
})
}
}
var peopleCache = mutableMapOf<String, Person>()
fun loadMoviesFull(): Observable<Movie> {
return service.listMovies()
.flatMap { filmResults -> Observable.from(filmResults.results) }
.flatMap { film ->
val movieObj = Movie(film.title, film.episodeId, ArrayList<Character>())
Observable.zip(
Observable.just(movieObj),
Observable.from(film.personUrls)
.flatMap { personUrl ->
Observable.concat(
getCache(personUrl),
service.loadPerson(Uri.parse(personUrl).lastPathSegment)
.doOnNext { person ->
peopleCache.put(personUrl, person)
}
).first()
}
.map { person ->
Character(person!!.name, person.gender)
}.toList(),
{ movie, characters ->
movie.characters.addAll(characters)
movie
})
}
}
private fun getCache(personUrl : String) : Observable<Person?>? {
return Observable.from(peopleCache.keys)
.filter { key ->
key == personUrl
}
.map { key ->
peopleCache[key]
}
}
class MainActivity : AppCompatActivity() {
var listView : ListView? = null
var movies = mutableListOf<String>()
var movieAdapter : ArrayAdapter<String>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
listView = ListView(this)
setContentView(listView)
movieAdapter = ArrayAdapter<String>(
this, android.R.layout.simple_list_item_1, movies)
listView?.adapter = movieAdapter
val api = StarWarsApi()
api.loadMovies()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({ movie ->
movies.add("${movie.title} -- ${movie.episodeId}")
}, { e ->
e.printStackTrace()
},{
movieAdapter?.notifyDataSetChanged()
})
}
}
package br.com.nglauber.starwarsrx.model
data class Movie (val title : String,
val episodeId : Int,
val characters : MutableList<Character>)
data class Character(val name : String,
val gender : String){
override fun toString(): String {
return "${name} / ${gender}"
}
}
{
"name": "Luke Skywalker",
"height": "172",
"mass": "77",
"hair_color": "blond",
"skin_color": "fair",
"eye_color": "blue",
"birth_year": "19BBY",
"gender": "male",
"homeworld": "http://swapi.co/api/planets/1/",
"films": [
"http://swapi.co/api/films/6/",
"http://swapi.co/api/films/3/",
"http://swapi.co/api/films/2/",
"http://swapi.co/api/films/1/",
"http://swapi.co/api/films/7/"
],
"species": [
"http://swapi.co/api/species/1/"
],
"vehicles": [
"http://swapi.co/api/vehicles/14/",
"http://swapi.co/api/vehicles/30/"
],
"starships": [
"http://swapi.co/api/starships/12/",
"http://swapi.co/api/starships/22/"
],
"created": "2014-12-09T13:50:51.644000Z",
"edited": "2014-12-20T21:17:56.891000Z",
"url": "http://swapi.co/api/people/1/"
}
buildscript {
ext.kotlin_version = '1.1.0'
ext.appcompat_version = '25.1.0'
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
jcenter()
}
}
package br.com.nglauber.starwarsrx.model.api
import br.com.nglauber.starwarsrx.model.Character
import br.com.nglauber.starwarsrx.model.Movie
import com.google.gson.GsonBuilder
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import rx.Observable
import java.util.*
class StarWarsApi {
val service: StarWarsApiDef
init {
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.BODY
val httpClient = OkHttpClient.Builder()
httpClient.addInterceptor(logging)
val gson = GsonBuilder().setLenient().create()
val retrofit = Retrofit.Builder()
.baseUrl("http://swapi.co/api/")
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(httpClient.build())
.build()
service = retrofit.create<StarWarsApiDef>(StarWarsApiDef::class.java)
}
fun loadMovies(): Observable<Movie>? {
return service.listMovies()
.flatMap { filmResults -> Observable.from(filmResults.results) }
.map { film ->
Movie(film.title, film.episodeId, ArrayList<Character>())
}
}
}
package br.com.nglauber.starwarsrx.model.api
import retrofit2.http.GET
import retrofit2.http.Path
import rx.Observable
interface StarWarsApiDef {
@GET("films")
fun listMovies() : Observable<FilmResult>
@GET("people/{personId}")
fun loadPerson(@Path("personId") personId : String) : Observable<Person>
}
api.loadMoviesFull()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({
movie ->
movies.add("${movie.title} -- ${movie.episodeId}\n ${movie.characters.toString() }")
}, {
e ->
e.printStackTrace()
},{
movieAdapter?.notifyDataSetChanged()
})
package br.com.nglauber.starwarsrx.model.api
import com.google.gson.annotations.SerializedName
data class FilmResult(val results : List<Film>)
data class Film (val title : String,
@SerializedName("episode_id")
val episodeId : Int,
@SerializedName("characters")
val personUrls : List<String>)
data class Person(val name : String,
val gender : String)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment