Olá povo,
Se você vem me seguindo aqui no blog, saiba que ele está abandonado porque migrei todas as postagens para o Medium.
Então me sigam por lá!
4br4ç05,
nglauber
Mostrando postagens com marcador Android. Mostrar todas as postagens
Mostrando postagens com marcador Android. Mostrar todas as postagens
sexta-feira, 10 de julho de 2020
terça-feira, 10 de julho de 2018
Como eu aprendi (um pouco sobre) RXJava
Olá povo,
Sempre que eu vejo um artigo legal sobre algo que estou interessado e não tenho tempo de ler naquele momento, eu mando um email pra mim mesmo com o link para ler depois. Eu sei, isso antigo, mas eu sou velho e funciona pra mim ;)
Resolvi compartilhar com vocês uma lista de links sobre RXJava que me ajudaram a entender um pouquinho sobre o assunto.
Android MeetUp 3 Anos - Programação Reativa Funcional com RxJava (Ubiratan Soares)
https://www.youtube.com/watch?v=0FpphC6hL5I
Refactoring for RxJava (Ubiratan Soares)
https://www.youtube.com/watch?v=391H38-7JYk
Rxify - a simple spell for complex RxJava operators (Garima Jain)
https://speakerdeck.com/ragdroid/rxify-a-simple-spell-for-complex-rxjava-operators
Exploring RxJava 2 for Android (Jake Wharton)
https://www.youtube.com/watch?v=htIXKI5gOQU
5 Not So Obvious Things About RxJava (Jag Saund)
https://medium.com/@jagsaund/5-not-so-obvious-things-about-rxjava-c388bd19efbc
Migrating from RxJava 1.0 to RxJava 2.0 and Learn RxJava by Examples (Amit Shekhar)
https://blog.mindorks.com/migrating-from-rxjava1-to-rxjava2-5dac0a94b4aa
An Introduction to Functional Reactive Programming (Dan Lew)
http://blog.danlew.net/2017/07/27/an-introduction-to-functional-reactive-programming/
Grokking RxJava (Dan Lew)
http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/
http://blog.danlew.net/2014/09/22/grokking-rxjava-part-2/
http://blog.danlew.net/2014/09/30/grokking-rxjava-part-3/
How to make complex requests simple with RxJava in Kotlin (Tamás Kozmér)
https://blog.mindorks.com/how-to-make-complex-requests-simple-with-rxjava-in-kotlin-ccec004c5d10
Don't break the chain: use RxJava's compose() operator (Dan Lew)
http://blog.danlew.net/2015/03/02/dont-break-the-chain/
A Complete Guide To Learn RxJava (Amit Shekhar)
https://blog.mindorks.com/a-complete-guide-to-learn-rxjava-b55c0cea3631
Multithreading with RxJava (Pierce Zaifman)
https://android.jlelse.eu/multithreading-with-rxjava-dadddc4f7a63
Adopting RxJava on Airbnb Android (Felipe Lima)
https://academy.realm.io/posts/kau-felipe-lima-adopting-rxjava-airbnb-android/
Começando com ReactiveX no Android (Ashraff Hathibelagal)
https://code.tutsplus.com/pt/tutorials/getting-started-with-reactivex-on-android--cms-24387
Programação Reativa com RxAndroid (Pedro Di Moura)
https://speakerdeck.com/pedrodimoura/programacao-reativa-com-rxandroid
Replace AsyncTask and AsyncTaskLoader with rx.Observable – RxJava Android Patterns (Ross Hambrick)
https://stablekernel.com/replace-asynctask-and-asynctaskloader-with-rx-observable-rxjava-android-patterns/
RxJava cheat sheet, with a pinch of Android (Oleg Shelajev)
https://zeroturnaround.com/rebellabs/rxjava-cheat-sheet-with-a-pinch-of-android/
RXJava2 by Example (Victor Grazi)
https://www.infoq.com/articles/rxjava2-by-example
4br4ç05,
nglauber
Sempre que eu vejo um artigo legal sobre algo que estou interessado e não tenho tempo de ler naquele momento, eu mando um email pra mim mesmo com o link para ler depois. Eu sei, isso antigo, mas eu sou velho e funciona pra mim ;)
Resolvi compartilhar com vocês uma lista de links sobre RXJava que me ajudaram a entender um pouquinho sobre o assunto.
Android MeetUp 3 Anos - Programação Reativa Funcional com RxJava (Ubiratan Soares)
https://www.youtube.com/watch?v=0FpphC6hL5I
Refactoring for RxJava (Ubiratan Soares)
https://www.youtube.com/watch?v=391H38-7JYk
Rxify - a simple spell for complex RxJava operators (Garima Jain)
https://speakerdeck.com/ragdroid/rxify-a-simple-spell-for-complex-rxjava-operators
Exploring RxJava 2 for Android (Jake Wharton)
https://www.youtube.com/watch?v=htIXKI5gOQU
5 Not So Obvious Things About RxJava (Jag Saund)
https://medium.com/@jagsaund/5-not-so-obvious-things-about-rxjava-c388bd19efbc
Migrating from RxJava 1.0 to RxJava 2.0 and Learn RxJava by Examples (Amit Shekhar)
https://blog.mindorks.com/migrating-from-rxjava1-to-rxjava2-5dac0a94b4aa
An Introduction to Functional Reactive Programming (Dan Lew)
http://blog.danlew.net/2017/07/27/an-introduction-to-functional-reactive-programming/
Grokking RxJava (Dan Lew)
http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/
http://blog.danlew.net/2014/09/22/grokking-rxjava-part-2/
http://blog.danlew.net/2014/09/30/grokking-rxjava-part-3/
How to make complex requests simple with RxJava in Kotlin (Tamás Kozmér)
https://blog.mindorks.com/how-to-make-complex-requests-simple-with-rxjava-in-kotlin-ccec004c5d10
Don't break the chain: use RxJava's compose() operator (Dan Lew)
http://blog.danlew.net/2015/03/02/dont-break-the-chain/
A Complete Guide To Learn RxJava (Amit Shekhar)
https://blog.mindorks.com/a-complete-guide-to-learn-rxjava-b55c0cea3631
Multithreading with RxJava (Pierce Zaifman)
https://android.jlelse.eu/multithreading-with-rxjava-dadddc4f7a63
Adopting RxJava on Airbnb Android (Felipe Lima)
https://academy.realm.io/posts/kau-felipe-lima-adopting-rxjava-airbnb-android/
Começando com ReactiveX no Android (Ashraff Hathibelagal)
https://code.tutsplus.com/pt/tutorials/getting-started-with-reactivex-on-android--cms-24387
Programação Reativa com RxAndroid (Pedro Di Moura)
https://speakerdeck.com/pedrodimoura/programacao-reativa-com-rxandroid
Replace AsyncTask and AsyncTaskLoader with rx.Observable – RxJava Android Patterns (Ross Hambrick)
https://stablekernel.com/replace-asynctask-and-asynctaskloader-with-rx-observable-rxjava-android-patterns/
RxJava cheat sheet, with a pinch of Android (Oleg Shelajev)
https://zeroturnaround.com/rebellabs/rxjava-cheat-sheet-with-a-pinch-of-android/
RXJava2 by Example (Victor Grazi)
https://www.infoq.com/articles/rxjava2-by-example
4br4ç05,
nglauber
segunda-feira, 14 de agosto de 2017
Como eu aprendi Kotlin
Olá povo,
Tenho ministrado palestras sobre Kotlin em vários lugares e uma pergunta muito comum que o pessoal vem fazendo é: onde e como aprender Kotlin?
Vou responder essa pergunta descrevendo como eu aprendi o que eu sei até agora.
Meu primeiro contato com Kotlin foi no segundo semestre de 2016 com o livro do Antonio Leiva que me deu uma boa base da linguagem e me motivou a estudar mais sobre o assunto.
Uma vez familiarizado com a linguagem, comecei a ler a documentação do Kotlin que é muito boa.
E navegando pela documentação achei o Kotlin Koans onde você aprende diversos recursos da linguagem por meio de 42 desafios que podem ser feitos on-line ou por meio do Kotlin Educational Plugin.
Após essas etapas iniciais, li um monte de artigos (muitos bem similares) onde cada um foi agregando um pouco aos meus estudos. Então resolvi compartilhar com vocês os links. Qualquer dúvida, é só falar ;)
Enjoy! :)
POSTS/SLIDES
Ten Kotlin Features To Boost Android DevelopmentKotlin: The Good, The Bad, and The Ugly
Why You Must Try Kotlin For Android Development ?
5 small things you probably don’t know about Kotlin
How “Effective Java” may have influenced the design of Kotlin
Kotlin 1.1: o que vem por aí?
Why You Should Start Using Kotlin to Supercharge Your Android Development in 2017
Android Coroutines with Kotlin: getting rid of runOnUiThread and Callbacks; cleaner thread handling; and more
Por que o Kotlin foi criado?
Lessons learned while converting to Kotlin with Android Studio
Exploring the Kotlin standard library
Handsome codes with Kotlin
Kotlin — A deeper look
Palestras do Jake Wharton
Nov/2015
Dez/2015
Mar/2017
Jul/2017
Kotlin Bytecode Generation and Runtime Performance
Understanding Generics and Variance in Kotlin
inline, noinline, crossinline — What do they mean?
An in-depth look at Kotlin’s initializers
Compare Java to Kotlin
Kotlin Workshop Material for you to use
Anko Coroutines
VÍDEOS
Kotlin para Android: O Despertar Da ForçaLive code with Kotlin: construindo o primeiro app usando Kotlin
Kotlin in Real Projects
Learn Path: Kotlin in depth
Muito provavelmente, vocês encontrarão todos esses links no site https://kotlin.link/.
Ah! Mas obviamente todos esses links não valeriam de muita coisa sem praticar. Por isso, desde o ano passado, todos os meus projetos (pessoais e profissionais) foram (e estão sendo) em Kotlin! \o/
Qualquer dúvida, deixe seu comentário ;)
4br4ç05,
nglauber
quarta-feira, 5 de julho de 2017
Falando de Android por aí :)
Olá pessoal,
Passei aqui apenas para deixar a lista dos próximos eventos que eu participarei. Estão todos convidados! :)
✔︎ Meetup: I/O Recap do GDG Recife
10/07/2017 - 19:15
https://www.meetup.com/GDG-Recife/events/241094820
Palestra: Turbinando o Desenvolvimento Android com Kotlin
✔︎ The Developers Conference (TDC) São Paulo - Trilha Android
19/07/2017 - 15:40
http://www.thedevelopersconference.com.br/tdc/2017/saopaulo/trilha-android
Palestra: Persistência de dados no SQLite com Room
✔︎ GDG Tech Tour Caruaru: I/O Recap
22/07/2017 - 13:00
https://www.facebook.com/events/1266327943476326
Palestra: Turbinando o Desenvolvimento Android com Kotlin
✔︎ Google Launchpad Build Porto Alegre
05/08/2017
https://events.withgoogle.com/google-launchpad-build-porto-alegre-05-de-agosto/
Palestra: Turbinando o Desenvolvimento Android com Kotlin
✔︎ Androidos Day em João Pessoa
11/08/2017 - 18:00 (Mini-Curso)
12/08/2017 - 13:30
http://androidosday.com/
Palestra: Turbinando o Desenvolvimento Android com Kotlin
✔︎ Google Developer Agency Day em São Paulo
16/08/2017
https://events.withgoogle.com/google-developers-agency-day/
Palestra: Turbinando o Desenvolvimento Android com Kotlin
✔︎ Android Dev Conference
24 e 25/08/2017
https://eventos.imasters.com.br/android-devconference
Palestra: Tudo o que você precisa saber sobre ConstraintLayout
✔︎ DevFest Maceió
23/09/2017
https://devfest.gdgmaceio.org/
Palestra: Turbinando o Desenvolvimento Android com Kotlin

✔︎ DevFest Cerrado em Goiânia
30/09/2017
https://devfestcerrado.com.br/
Palestra: Turbinando o Desenvolvimento Android com Kotlin
DevFest Paraná (Londrina)
11/11/2017
https://devfestpr.org/
Palestra: ?
4br4ç05,
nglauber
Passei aqui apenas para deixar a lista dos próximos eventos que eu participarei. Estão todos convidados! :)
✔︎ Meetup: I/O Recap do GDG Recife
10/07/2017 - 19:15
https://www.meetup.com/GDG-Recife/events/241094820
Palestra: Turbinando o Desenvolvimento Android com Kotlin
✔︎ The Developers Conference (TDC) São Paulo - Trilha Android
19/07/2017 - 15:40
http://www.thedevelopersconference.com.br/tdc/2017/saopaulo/trilha-android
Palestra: Persistência de dados no SQLite com Room
✔︎ GDG Tech Tour Caruaru: I/O Recap
22/07/2017 - 13:00
https://www.facebook.com/events/1266327943476326
Palestra: Turbinando o Desenvolvimento Android com Kotlin
✔︎ Google Launchpad Build Porto Alegre
05/08/2017
https://events.withgoogle.com/google-launchpad-build-porto-alegre-05-de-agosto/
Palestra: Turbinando o Desenvolvimento Android com Kotlin
✔︎ Androidos Day em João Pessoa
11/08/2017 - 18:00 (Mini-Curso)
12/08/2017 - 13:30
http://androidosday.com/
Palestra: Turbinando o Desenvolvimento Android com Kotlin
✔︎ Google Developer Agency Day em São Paulo
16/08/2017
https://events.withgoogle.com/google-developers-agency-day/
Palestra: Turbinando o Desenvolvimento Android com Kotlin
✔︎ Android Dev Conference
24 e 25/08/2017
https://eventos.imasters.com.br/android-devconference
Palestra: Tudo o que você precisa saber sobre ConstraintLayout
✔︎ DevFest Maceió
23/09/2017
https://devfest.gdgmaceio.org/
Palestra: Turbinando o Desenvolvimento Android com Kotlin

✔︎ DevFest Cerrado em Goiânia
30/09/2017
https://devfestcerrado.com.br/
Palestra: Turbinando o Desenvolvimento Android com Kotlin
DevFest Paraná (Londrina)
11/11/2017
https://devfestpr.org/
Palestra: ?
4br4ç05,
nglauber
segunda-feira, 3 de julho de 2017
Introdução ao Kotlin com Android Studio
Olá pessoal,
Decidi fazer esse vídeo para ajudar aqueles que querem dar os primeiros passos com Kotlin utilizando Android Studio.
Qualquer dúvida, deixe seu comentário. ;)
4br4ço5,
nglauber
Decidi fazer esse vídeo para ajudar aqueles que querem dar os primeiros passos com Kotlin utilizando Android Studio.
Qualquer dúvida, deixe seu comentário. ;)
4br4ço5,
nglauber
segunda-feira, 22 de maio de 2017
Architecture Components do Android
Olá povo,
O Google I/O 2017 foi repleto de novidades fantásticas para a plataforma Android. Entre elas, duas foram fundamentais para os desenvolvedores Android: Kotlin e Architecture Components.

Apesar de podermos desenvolver aplicativos Android utilizando Kotlin nas versões anteriores do Android Studio por meio de um plugin instalado à parte, agora ao criar um projeto poderemos selecionar a linguagem de nossa preferência (Java ou Kotlin).
Os Architecture Components vieram para facilitar a implementação de aplicativos de uma forma mais robusta e padronizada, e nesse post vou mostrar um exemplo simples de como utilizar essas APIs.
Na lista de dependências, além do gradle, adicionamos o plugin do Kotlin. Por fim, na lista de repositórios, devemos adicionar o "maven.google.com".
Agora vá até o build.gradle do módulo da sua aplicação e faça os seguintes ajustes.
Agora vamos definiremos a DAO, a interface que possuirá os métodos para interagir com o banco de dados.
Apesar de não estarmos utilizando esse recurso, no método deletePerson() permitimos excluir vários registros ao mesmo tempo utilizando um vararg. A parte mais interessante é o método listAll() que retorna um LiveData de uma lista de objetos Person.
Utilizando o LiveData quando qualquer registro for inserido, alterado ou excluído, a lista será automaticamente atualizada.
O último passo para podermos utilizar o Room, é definir uma classe que herda de RoomDatabase como mostraremos a seguir.
Essa classe será um singleton que é inicializado por meio do método Room.databaseBuilder onde passamos o contexto, a referência à nossa classe e o nome do banco. Perceba que estamos utilizando o método allowMainThreadQueries() que não é recomendado, pois devemos realizar as consultas em uma thread separada, mas não estamos fazendo isso aqui para simplificar o exemplo.
O método peopleDao() retornará uma instância da implementação do nosso DAO.
Faremos uma classe similar para a tela de cadastro, mas apenas para isolar o acesso ao banco da nossa UI.
Não vou mostrar o layout dessa activity aqui, mas ele possui apenas uma ListView com o id @+id/listview e uma FloatingActionButton com o id @+id/fab. Perceba que estamos acessando os componentes de UI usando simplesmente o seu id. Isso é feito graças ao kotlinx (Kotlin Extensions).
Ao clicar no FAB, o PersonFormFragment (que mostraremos a seguir) é exibido. Perceba que estamos obtendo o ViewModel dessa tela por meio da classe ViewModelProviders e passando o nome da classe.
Com o ViewModel, obtemos a lista de pessoas e chamamos o método observe para sabermos quando a listagem mudou. Nesse caso, definimos um adapter para o nosso listView e atribuímos o evento de click no item. Perceba que como não estamos utilizando todos os parâmetros, estamos utilizando o "_" no lugar dos respectivos nomes.
A última classe é tela de cadastro que é um DialogFragment.
No onAttach estamos inicializando nosso ViewModel e obtendo o objeto Person passado da tela de listagem. Se não tivermos passado esse objeto, criamos um novo. Perceba que nessa instrução estamos usando "?" nos arguments, pois ele pode ser null, no "as?" pois não pode ser feito um cast de null para Person (isso se chama save cast) e por fim utilizamos o "elvis operator", pois caso a instrução anterior seja nula, criamos um novo objeto Person.
Nada de especial no onCreateView, mas no onViewCreated temos apenas uma instrução interessante para quem é novo em Kotlin que é o if/else retornando um valor (seria o mesmo que o ternário do Java "?:").
Nos métodos removePerson chamamos nosso ViewModel para excluir o objeto e no savePerson para salvar o objeto. Por fim, nossa classe possui o "factory method" newInstance para passarmos o objeto pessoa como parâmetro para a tela de cadastro no caso de uma alteração.
O resultado deve ficar como a seguir:
Essa foi uma pequena introdução de como utilizar as bibliotecas de arquitetura lançadas no Google IO de 2017 utilizando Kotlin. Obviamente existe muito mais a explorar, mas espero que esse post já ajude a dar os primeiros passos com essas APIs.
Para saber mais, assistam esses vídeos do Google IO e a documentação dessas libs. ;)
Architecture Components - Introduction
https://www.youtube.com/watch?v=FrteWKKVyzI
Architecture Components - Solving the Lifecycle Problem
https://www.youtube.com/watch?v=bEKNi1JOrNs
Architecture Components - Persistence and Offline
https://www.youtube.com/watch?v=MfHsPGQ6bgE
Documentação oficial
https://developer.android.com/topic/libraries/architecture/index.html
4br4ç05,
nglauber
O Google I/O 2017 foi repleto de novidades fantásticas para a plataforma Android. Entre elas, duas foram fundamentais para os desenvolvedores Android: Kotlin e Architecture Components.

Apesar de podermos desenvolver aplicativos Android utilizando Kotlin nas versões anteriores do Android Studio por meio de um plugin instalado à parte, agora ao criar um projeto poderemos selecionar a linguagem de nossa preferência (Java ou Kotlin).
Os Architecture Components vieram para facilitar a implementação de aplicativos de uma forma mais robusta e padronizada, e nesse post vou mostrar um exemplo simples de como utilizar essas APIs.
Adicionando as dependências
Para implementar esse projeto, eu utilizei o Android Studio 2.4 com o plugin 1.1.2 do Kotlin. Mas se quiser utilizar a versão preview do Android Studio 3.0 eu creio que você não terá muitos problemas. Crie um novo projeto com suporte a Kotlin e nomeie a sua activity principal como ListPeopleActivity. Com o projeto criado, vamos fazer as seguintes mudanças no build.gradle do seu projeto como a seguir:buildscript {
ext.gradle_version = '2.3.2'
ext.kotlin_version = '1.1.2-3'
ext.anko_version = '0.8.2'
ext.support_version = '25.3.1'
ext.arch_lifecycle_version = "1.0.0-alpha1"
ext.arch_room_version = "1.0.0-alpha1"
repositories {
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:$gradle_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
jcenter()
maven { url 'https://maven.google.com' }
mavenCentral()
}
}
Aqui criamos uma série de variáveis com as versões das bibliotecas que utilizaremos no projeto. Isso não é obrigatório, mas facilita a legibilidade do arquivo e evita erros e conflitos entre versões das bibliotecas. Adicionamos a versão do Gradle, do Kotlin, do Anko (que é uma biblioteca para facilitar o acesso aos componentes de UI), da support library e finalmente, das bibliotecas de arquitetura (lifecycle e room).Na lista de dependências, além do gradle, adicionamos o plugin do Kotlin. Por fim, na lista de repositórios, devemos adicionar o "maven.google.com".
Agora vá até o build.gradle do módulo da sua aplicação e faça os seguintes ajustes.
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
// Nada muda aqui...
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile "org.jetbrains.anko:anko-common:$anko_version"
compile "com.android.support:appcompat-v7:$support_version"
compile "com.android.support:design:$support_version"
compile "com.android.support:support-v4:$support_version"
compile "android.arch.lifecycle:runtime:$arch_lifecycle_version"
compile "android.arch.lifecycle:extensions:$arch_lifecycle_version"
compile "android.arch.persistence.room:runtime:$arch_room_version"
kapt "android.arch.lifecycle:compiler:$arch_lifecycle_version"
kapt "android.arch.persistence.room:compiler:$arch_room_version"
}
Além do plugin do Android, estamos aplicando o plugin do Kotlin e o de extensões para o Kotlin. Na seção de dependências, adicionamos todas as bibliotecas que utilizaremos nesse projeto. O kapt (Kotlin Annotation Process Tool) substitui o "annotationProcessor" para projeto sem Kotlin. Perceba que utilizamos o kapt para as bibliotecas de arquitetura, pois ela geram o código em tempo de compilação. Isso deve ser feito para outras bibliotecas que fazem esse trabalho (Dagger, DataBinding, etc.).Definindo o acesso ao banco
Para simplificar o tutorial e facilitar o entendimento, nosso aplicativo será um cadastro simples de pessoas, onde cada pessoa possuirá o primeiro nome, sobrenome e idade. Para tal, definiremos a classe a seguir:import android.arch.persistence.room.Entity
import android.arch.persistence.room.PrimaryKey
import java.io.Serializable
@Entity
data class Person(
@PrimaryKey(autoGenerate = true) var id: Long = 0L,
var firstName: String = "",
var lastName: String = "",
var age: Int = 0) : Serializable
Criamos uma data class anotada com @Entity, o que indica que objetos dessa classe serão persistidos. Todos os parâmetros têm valores default, então podemos criar objetos dessa classe passando nenhum parâmetro. Uma outra curiosidade nessa classe é que devemos adicionar um atributo como @PrimaryKey, nesse exemplo, ele será gerado automaticamente, então definimos a propriedade autoGenerate para true.Agora vamos definiremos a DAO, a interface que possuirá os métodos para interagir com o banco de dados.
import android.arch.lifecycle.LiveData
import android.arch.persistence.room.*
import android.arch.persistence.room.OnConflictStrategy.IGNORE
@Dao
interface PeopleDao {
@Insert(onConflict = IGNORE)
fun insertPerson(person: Person)
@Update
fun updatePerson(person: Person)
@Delete
fun deletePerson(vararg people: Person)
@Query("SELECT * FROM Person ORDER BY firstName")
fun listAll(): LiveData<List<Person>>
}
Nossa interface está anotada com @Dao e os métodos de inserir, atualizar, excluir e listar estão anotados respectivamente com @Insert, @Update, @Delete e @Query. O método insertPerson(Person) possui em sua anotação a propriedade onConflict definida como IGNORE, indicando que caso haja um conflito no momento da inserção o registro será ignorado.Apesar de não estarmos utilizando esse recurso, no método deletePerson() permitimos excluir vários registros ao mesmo tempo utilizando um vararg. A parte mais interessante é o método listAll() que retorna um LiveData de uma lista de objetos Person.
Utilizando o LiveData quando qualquer registro for inserido, alterado ou excluído, a lista será automaticamente atualizada.
O último passo para podermos utilizar o Room, é definir uma classe que herda de RoomDatabase como mostraremos a seguir.
import android.arch.persistence.room.Database
import android.arch.persistence.room.Room
import android.arch.persistence.room.RoomDatabase
import android.content.Context
@Database(
entities = arrayOf(Person::class),
version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun peopleDao(): PeopleDao
companion object {
private val DB_NAME = "dbPeople"
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase? {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
DB_NAME)
.allowMainThreadQueries()
.build()
}
return INSTANCE
}
fun destroyInstance() {
INSTANCE = null
}
}
}
Na anotação @Database informamos quais entidades serão persistidas utilizando a propriedade "entities" e a versão do banco. Perceba que essa é uma classe abstrata, pois assim como a nossa interface DAO, a implementação será gerada em tempo de compilação.Essa classe será um singleton que é inicializado por meio do método Room.databaseBuilder onde passamos o contexto, a referência à nossa classe e o nome do banco. Perceba que estamos utilizando o método allowMainThreadQueries() que não é recomendado, pois devemos realizar as consultas em uma thread separada, mas não estamos fazendo isso aqui para simplificar o exemplo.
O método peopleDao() retornará uma instância da implementação do nosso DAO.
Definindo os ViewModels
Definida nossa camada de acesso ao banco, partiremos agora para a definição dos ViewModels do nosso pequeno projeto. Primeiramente, vamos criar uma classe que será utilizada na tela de listagem e será responsável por manter o resultado da busca durante a rotação da tela do aparelho sem ter que fazer uma nova consulta ao banco.import android.app.Application
import android.arch.lifecycle.AndroidViewModel
import android.arch.lifecycle.LiveData
class ListPeopleViewModel(app : Application) : AndroidViewModel(app) {
var livePeople: LiveData<List<Person>>? = null
var db: PeopleDao? = null
private fun getDao() : PeopleDao? {
if (db == null) {
db = AppDatabase.getDatabase(getApplication())?.peopleDao()
}
return db
}
fun getPeople(): LiveData<List<Person>> {
if (livePeople == null) {
livePeople = getDao()?.listAll()
}
return livePeople as LiveData<List<Person>>
}
}
Nossa classe herda de AndroidViewModel e está mantendo a LiveData da lista de Person. Dessa forma, caso a lista seja nula, carregamos do banco, caso contrário apenas a retornamos.Faremos uma classe similar para a tela de cadastro, mas apenas para isolar o acesso ao banco da nossa UI.
import android.app.Application
import android.arch.lifecycle.AndroidViewModel
class PersonFormViewModel(app : Application) : AndroidViewModel(app) {
private var db: PeopleDao? = null
private fun peopleDao() : PeopleDao? {
if (db == null) {
db = AppDatabase.getDatabase(getApplication())?.peopleDao()
}
return db
}
fun savePerson(person : Person) {
if (person.id == 0L) {
peopleDao()?.insertPerson(person)
} else {
peopleDao()?.updatePerson(person)
}
}
fun deletePerson(person: Person) {
peopleDao()?.deletePerson(person)
}
}
O método savePerson(Person) irá inserir o objeto se o seu id for igual a zero ou atualizá-lo caso contrário. Já o método deletePerson(Person) excluirá o objeto Person.Juntando tudo
Finalmente vamos implementar as telas da aplicação, começando pela tela de listagem.import android.arch.lifecycle.LifecycleRegistry
import android.arch.lifecycle.LifecycleRegistryOwner
import android.arch.lifecycle.Observer
import android.arch.lifecycle.ViewModelProviders
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.ArrayAdapter
import kotlinx.android.synthetic.main.activity_list_people.*
class ListPeopleActivity : AppCompatActivity(), LifecycleRegistryOwner {
var lifecycleRegistry = LifecycleRegistry(this)
override fun getLifecycle(): LifecycleRegistry = lifecycleRegistry
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_list_people)
fab.setOnClickListener {
PersonFormFragment().show(supportFragmentManager, "form")
}
val model = ViewModelProviders.of(this).get(ListPeopleViewModel::class.java)
model.getPeople().observe(this, Observer { people ->
listview.adapter = ArrayAdapter<Person>(
this@ListPeopleActivity,
android.R.layout.simple_list_item_1,
people)
listview.setOnItemClickListener { _, _, position, _ ->
val person = people?.get(position)
if (person != null) {
PersonFormFragment.newInstance(person).show(supportFragmentManager, "form")
}
}
})
}
override fun onDestroy() {
AppDatabase.destroyInstance()
super.onDestroy()
}
}
Nossa classe herda de AppCompatActivity e implementa LifecycleRegistryOwner. Essa interface requer que implementemos o método getLifecycle() que retorna um objeto LifecycleRegistry. Poderíamos simplesmente herdade de LifecycleActivity, mas essa classe herda de FragmentActivity, então perderíamos a ActionBar padrão que é adicionada.Não vou mostrar o layout dessa activity aqui, mas ele possui apenas uma ListView com o id @+id/listview e uma FloatingActionButton com o id @+id/fab. Perceba que estamos acessando os componentes de UI usando simplesmente o seu id. Isso é feito graças ao kotlinx (Kotlin Extensions).
Ao clicar no FAB, o PersonFormFragment (que mostraremos a seguir) é exibido. Perceba que estamos obtendo o ViewModel dessa tela por meio da classe ViewModelProviders e passando o nome da classe.
Com o ViewModel, obtemos a lista de pessoas e chamamos o método observe para sabermos quando a listagem mudou. Nesse caso, definimos um adapter para o nosso listView e atribuímos o evento de click no item. Perceba que como não estamos utilizando todos os parâmetros, estamos utilizando o "_" no lugar dos respectivos nomes.
A última classe é tela de cadastro que é um DialogFragment.
import android.arch.lifecycle.ViewModelProviders
import android.content.Context
import android.os.Bundle
import android.support.v4.app.DialogFragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.fragment_person_form.*
class PersonFormFragment : DialogFragment() {
lateinit var person : Person
lateinit var viewModel : PersonFormViewModel
override fun onAttach(context: Context?) {
super.onAttach(context)
viewModel = ViewModelProviders.of(this).get(PersonFormViewModel::class.java)
person = arguments?.getSerializable(EXTRA_PERSON) as? Person ?: Person()
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater?.inflate(R.layout.fragment_person_form, container, false)
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
edtFirstName.setText(person.firstName)
edtLastName.setText(person.lastName)
edtAge.setText(if (person.age != 0 || person.id != 0L) person.age.toString() else "")
btnRemove.visibility = if (person.id == 0L) View.GONE else View.VISIBLE
btnCancel.setOnClickListener { dismiss() }
btnSave.setOnClickListener { savePerson() }
btnRemove.setOnClickListener { removePerson() }
}
private fun removePerson() {
viewModel.deletePerson(person)
dismiss()
}
private fun savePerson() {
person.firstName = edtFirstName.text.toString()
person.lastName = edtLastName.text.toString()
person.age = edtAge.text.toString().toInt()
viewModel.savePerson(person)
dismiss()
}
companion object {
val EXTRA_PERSON = "person"
fun newInstance(person: Person) : PersonFormFragment {
val args = Bundle()
args.putSerializable(EXTRA_PERSON, person)
val f = PersonFormFragment()
f.arguments = args
return f
}
}
}
Mais uma vez estamos omitindo o arquivo de layout aqui, mas ele possui basicamente três EditText (edtFirstName, edtLastName e edtAge) para os respectivos campos da classe Person, e três botões (btnSave, btnRemove, btnCancel) para salvar, remover e cancelar o dialog. Sendo que o segundo só estará habilitado se estivermos editando uma pessoa.No onAttach estamos inicializando nosso ViewModel e obtendo o objeto Person passado da tela de listagem. Se não tivermos passado esse objeto, criamos um novo. Perceba que nessa instrução estamos usando "?" nos arguments, pois ele pode ser null, no "as?" pois não pode ser feito um cast de null para Person (isso se chama save cast) e por fim utilizamos o "elvis operator", pois caso a instrução anterior seja nula, criamos um novo objeto Person.
Nada de especial no onCreateView, mas no onViewCreated temos apenas uma instrução interessante para quem é novo em Kotlin que é o if/else retornando um valor (seria o mesmo que o ternário do Java "?:").
Nos métodos removePerson chamamos nosso ViewModel para excluir o objeto e no savePerson para salvar o objeto. Por fim, nossa classe possui o "factory method" newInstance para passarmos o objeto pessoa como parâmetro para a tela de cadastro no caso de uma alteração.
O resultado deve ficar como a seguir:
Essa foi uma pequena introdução de como utilizar as bibliotecas de arquitetura lançadas no Google IO de 2017 utilizando Kotlin. Obviamente existe muito mais a explorar, mas espero que esse post já ajude a dar os primeiros passos com essas APIs.
Para saber mais, assistam esses vídeos do Google IO e a documentação dessas libs. ;)
Architecture Components - Introduction
https://www.youtube.com/watch?v=FrteWKKVyzI
Architecture Components - Solving the Lifecycle Problem
https://www.youtube.com/watch?v=bEKNi1JOrNs
Architecture Components - Persistence and Offline
https://www.youtube.com/watch?v=MfHsPGQ6bgE
Documentação oficial
https://developer.android.com/topic/libraries/architecture/index.html
4br4ç05,
nglauber
sexta-feira, 3 de março de 2017
RXJava + Kotlin + Retrofit + Star Wars API

Olá povo,
Há algum tenho venho estudando dois tópicos relacionados a Android que vem me deixando bem empolgado: Kotlin e RX Java.
Kotlin é uma liguagem dinâmica para JVM desenvolvida pela JetBrains que traz diversas features não existentes no Java. E o RX Java, bem a grosso modo, é uma biblioteca nos ajuda a trabalhar com sequência de dados que podem estar em threads separadas de uma maneira bem mais simples.
O intuito deste post não é como dar os primeiros passos com RX ou Kotlin, e sim documentar e compartilhar o que eu aprendi ao tentar implementar um exemplo "simples" com esse conjunto de linguagem+biblioteca+api.
Nesse post vou mostrar:
- Como acessar a Star Wars API utilizando a biblioteca Retrofit;
- Fazer as requisições utilizando RX Java + Retrofit;
- e todo o código é escrito em Kotlin.
Configuração do projeto
Primeira coisa que você deve fazer é instalar o plugin do Kotlin no Android Studio. Você pode seguir esse tutorial aqui:https://blog.jetbrains.com/kotlin/2013/08/working-with-kotlin-in-android-studio/
A versão atual no momento da escrita desse post é a 1.1.0-release-Studio2.3-1
Instalado o plugin, crie um novo projeto no Android Studio.
Deixe o build.gradle do seu projeto como a seguir:
buildscript {
ext.kotlin_version = '1.1.0'
ext.appcompat_version = '25.1.0'
ext.retrofit_version = '2.2.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()
}
}
O que temos de diferente aqui é que estamos criando algumas variáveis com as versões do Kotlin e da biblioteca de compatibilidade. E na seção de dependências adicionamos o plugin do Kotlin para o Gradle.
Vá agora até o build.gradle do módulo, faça as seguintes alterações:
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:$retrofit_version"
// Adapter do Retrofit para retornar objetos observáveis
compile "com.squareup.retrofit2:adapter-rxjava:$retrofit_version"
// Converter do Retrofit para utilizar o Gson para tratar a resposta do servidor
compile "com.squareup.retrofit2:converter-gson:$retrofit_version"
// Interceptor para visualizar os logs das requisições do Retrofit
compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
...
}
Aplicamos o plugin do Kotlin e adicionamos as dependências que utilizaremos no projeto. A motivação de cada uma está comentada acima.A API do Star Wars
Vamos utilizar nesse exemplo dois endpoints da API do Star Wars: films e people.Se fizermos uma requisição para http://swapi.co/api/films o resultado será o JSON com a lista dos filmes de Star Wars.
{
"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...
]
}
Se utilizarmos http://swapi.co/api/films/1 ele trará apenas o filme primeiro filme.Percebam que os campos "characters", "planets", "species", "starships" e "vehicles" retornam um array de strings, onde cada string representa o endereço para aquela determinada informação. Sendo assim, se acessarmos a URL http://swapi.co/api/people/1/ teremos o resultado abaixo.
{
"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/"
}
Note que temos uma referência cruzada aqui. O filme possui a lista de personagens e o personagem possui uma lista dos filmes (no campo "films") em que ele participou.Entendida a API, vamos começar a brincar com ela!
Definindo as classes de modelo
Um dos recursos que eu gosto bastante do Kotlin é a possibilidade de criar data classes, que são os nosso famosos POJOs. É possível criar várias classes públicas no mesmo arquivo e no Kotlin temos o conceito de propriedade, ou seja, não é preciso definir os gets e sets (embora você possa customiza-los).Crie o arquivo DataClassesWeb.kt (ou o nome que preferir) que conterá as classes que representarão o retorno das requisições que faremos a API.
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)
A classe FilmResult representará o retorno da chamada que faremos a lista de filmes. Ela possui a propriedade results que é uma lista de Film. A classe Film, por sua vez, possui o título, o id do episódio e a lista das URLs para obtermos as informações dos personagens. Por fim, a classe Person possui o nome e o gênero do personagem.
Agora crie mais um arquivo chamado DataClasses.kt com as classes "de negócio" da nossa aplicação.
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}"
}
}
Como podemos observar, essas classes são bem parecidas, mas preferi separar as classes de retorno de API, das que serão utilizadas na UI.Definindo as chamadas à API com Retrofit
Nesse exemplo, vamos utilizar apenas dois endpoints da API do Star Wars: o que retorna a listagem de filmes; e o que obtém o personagem pelo seu id. Sendo assim, crie o arquivo StarWarsApiDef.kt e deixe-o como a seguir: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>
}
Os métodos seguem o que está especificado na API do Star Wars. Para obtermos a lista de filmes, realizamos uma requisição do tipo GET, para o endpoint "films" que retorna um objeto (FilmResult) que possui uma lista de filmes (Film). E para obter um personagem específico, utilizamos o endpoint "people/id_do_personagem".Percebam que estamos retornando um Observable<FilmResult> e um Observable<Person>. A classe Observable é um dos principais componentes do RXJava (senão o principal). Se você não está familiarizado com esses conceitos, sugiro assistir as palestras do Ubiratan Soares que é uma verdadeira aula sobre o assunto (veja os links no final do post).
Definida a classe com os endpoints, vamos criar a implementação que utilizará esses endpoints. Crie o arquivo StarWarsApi.kt e deixe-o como a seguir.
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>())
}
}
}
Essa classe possui um atributo chamado service do tipo StarWarsApiDef (que criamos anteriormente). Dentro do bloco init{} fazemos a inicialização e configuração do serviço do Retrofit. Adicionamos o HttpLoggingInterceptor ao OkHttpClient para podermos visualizar no Logcat as requisições e as respostas feitas pelo retrofit. Instanciamos o GsonBuilder para que o JSON retornado seja tratado pela biblioteca Gson. Utilizamos o RxJavaCallAdapterFactory para o Retrofit retornar o resultado em forma de objetos observáveis. Por fim, utilizamos o Retrofit.Builder para criar a instância do serviço.
O operador flatMap permite iterar sobre um Observable e retornar um novo Observable. É isso que estamos fazendo no método loadMovies. Estamos chamando o método listMovies() do nosso serviço que retorna um Observable de FilmResult, então utilizamos o operador flatMap para obter o FilmResult e geramos um novo Observable de Film com os filmes por meio do método Observable.from(). Em seguida, iterarmos por cada filme (Film) da lista (que é um Observable de Film) e o transformamos em um Observable de Movie, que é o tipo de retorno do método.
Chamando o serviço na Activity
Vamos ver como acessar o nosso serviço na interface gráfica. Se você ainda não converteu sua activity para Kotlin, faça isso acessando o menu "Code > Convert Java File to Kotlin file". E deixe sua activity como a seguir.class MainActivity : AppCompatActivity() {
lateinit var listView : ListView
lateinit var movieAdapter : ArrayAdapter<String>
var movies = mutableListOf<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
listView = ListView(this)
setContentView(listView)
movieAdapter = ArrayAdapter(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()
})
}
}
Perceba que estamos invocando o método loadMovies() da nossa API. Como vimos anteriormente, esse método retorna um Observable, ou seja, um observável. Nossa tela observará esse objeto, então ela será um Observer. Estamos dizendo que queremos que esse objeto seja criado em background na thread de I/O usando o método subscribeOn(Schedulers.io()). Ele será criado em background, mas queremos observá-lo na main thread do Android, o que nos permitirá atualizar a tela.
Ao chamarmos o método subscribe, temos 3 expressões lambda: onNext, que é chamado a cada novo objeto Movie retornado; onError disparado se algum erro ocorrer; e o onCompleted quando a sequência de objetos termina.No onNext estamos adicionando os filmes na lista (em formato de string para simplificar) e no onCompleted estamos atualizando o adapter para exibir a listagem na tela.
Execute a aplicação e você deverá ver a lista de filmes.
Mas cada filme não deveria ter os seus respectivos personagens?
Sim. Mas para uma tela de listagem isso demora um bocado, pois cada filme tem vários personagens. Então seria melhor na tela de detalhe exibir os personagens. Mas fiquei curioso em saber como fazer isso com RX e resolvi fazer o teste. Vamos voltar ao arquivo StarWarsApi.kt e adicione o seguinte método.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
})
}
}
Olha que loucura isso! :)Fazemos a requisição da lista de filmes, e para cada filme temos que pegar a lista de URLs dos personagens e apenas quando cada objeto filme estiver completo, é passamos para o próximo. Para fazer isso, utilizamos o operador zip(), pois ele junta o resultado de dois Observables e retorna um novo Observable.
Podemos testar isso agora na nossa Activity.
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()
})
Na listagem deve aparecer o filme e os respectivos personagens. Essa requisição deve demorar vários segundos.Fazendo cache!
Alguns personagens aparecem em vários filmes. Por isso seria interessante fazermos cache dos dados desses personagens para não fazermos requisições desnecessárias. Vamos fazer um pequeno ajuste no StarWarsApi.kt.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]
}
}
O atributo peopleCache armazena as instâncias de Person. Então na hora que estamos varrendo a lista de personagens utilizamos o operador concat().first() para pegar o primeiro objeto do cache (se existir) ou da API. Quando buscamos da API, adicionamos o objeto no cache, isso é feito no método doOnNext(). Agora estamos fazendo o cache em memória. Mas poderíamos (e deveríamos) fazer em disco.Como comentei anteriormente, a implementação sem cache demora bastante (uns 30 segundos), mas essa implementação com cache foi bem melhor. Mesmo assim, acho que não seria legal esperar esse tempo todo para trazer a listagem. Seria melhor exibir a listagem de personagens na tela de detalhe de um único filme. Entretanto foi interessante para explorar o potencial do RX com múltiplas requisições.
Ao terminar de escrever o post, notei que tinha muita informação, então resolvi fazer um vídeo mostrado passo a passo a construção do exemplo e tentando explicar melhor a implementação. Espero que gostem :)
Qualquer dúvida, deixem seus comentários.
4br4ç05,
nglauber
Referências
Site oficial do Kotlinhttps://kotlinlang.org/
Site oficial do RXJava
https://github.com/ReactiveX/RxJava
StarWars API
https://swapi.co
Apresentações Ubiratan Soares
Programação Reativa Funcional com RxJava
Vídeo: https://www.youtube.com/watch?v=0FpphC6hL5I
Slides: https://speakerdeck.com/ubiratansoares/rxjava-for-android
Refactoring for RxJava
Vídeo: https://www.youtube.com/watch?v=391H38-7JYk
Sllides: https://speakerdeck.com/ubiratansoares/refactoring-for-rxjava
Dan Lew cache in RX
http://blog.danlew.net/2015/06/22/loading-data-from-multiple-sources-with-rxjava/
Livro de RX
http://www.oreilly.com/programming/free/rxjava-for-android-app-development.csp
Livro de Kotlin
https://antonioleiva.com/kotlin/
sexta-feira, 23 de dezembro de 2016
2016 foi Loko!
Olá povo,
Primeiramente peço desculpas por não ter postado muito esse ano, mas se vocês lerem esse texto, vão entender um pouquinho o motivo. 2016 foi um ano muito intenso, com muitas mudanças que exigiram bastante de mim.
Dominando o Android 2ª edição
No começo do ano saiu a 2ª edição do meu livro, o "Dominando o Android" com uma série de correções e novos conteúdos. Muitas coisas que eu gostaria ter colocado na primeira edição entraram nessa edição e eu fiquei muito feliz com o resultado. Ainda não estou trabalhando na 3ª edição, mas creio que teremos novidades em junho ou julho de 2017.
Despedida do CESAR
Sem sombra de dúvida o evento mais marcante para mim foi minha saída do CESAR. No mês de março, após 10 anos, resolvi pedir demissão, simplesmente porque o que a instituição esperava de mim não estava alinhado com os meus objetivos profissionais. Então, ao invés de ficar reclamando pelos corredores ou fazer um trabalho mau feito, resolvi sair. Mas o CESAR estará sempre no meu coração por ser um lugar muito legal e cheio de pessoas bacanas. Tanto que, pelo menos uma vez por semana, saio de casa apenas para almoçar com amigos que trabalham ou trabalharam no CESAR :)
Mesa e Mokriya
Quando estava querendo sair do CESAR, meu amigo Leocádio Tiné me convidou para para substituí-lo lá na Mesa. Uma empresa muito bacana aqui de Recife com cerca de 12 pessoas. Então em abril comecei a trabalhar lá. O desafio era bem diferente do CESAR, onde normalmente tínhamos equipes com várias pessoas trabalhando em um mesmo projeto. A demanda de aplicativos lá era/é bem grande e cada desenvolvedor ficava responsável por fazer um app do começo ao fim. Achei isso bem bacana e isso me motivou bastante.
Com certeza eu ficaria na Mesa por um bom tempo, devido ao ambiente e o trabalho que eram bem legais. Mas o meu grande amigo Douglas Drummond ficou sabendo que eu tinha saído do CESAR e me convidou para entrar no processo seletivo da Mokriya, uma empresa de Cupertino onde a maioria dos funcionários trabalha remotamente. Participei do processo, fui aprovado e como a proposta foi bem interessante, tive que deixar a Mesa para trabalhar de casa, mais uma experiência nova para mim... Tenho que escrever um post sobre isso :)
Quero aproveitar para agradecer a Antônio, Arthur e Tiago que me deram essa oportunidade de fazer parte da Mesa. Infelizmente foi por pouco tempo, mas foi muito bom. E um agradecimento muito especial a Douglas por ter apostado em mim, mesmo tendo conversado pessoalmente comigo apenas duas ou três vezes. Valeu mesmo! ;)
Eventos nacionais
Em termos de eventos, esse ano eu não participei tanto, comparado aos anos anteriores.
Em parceria com o GDG Recife, pelo segundo ano consecutivo eu fui mentor do Study Jam que é uma iniciativa do Google em parceria com a Udacity para ministrar cursos gratuitos sobre tecnologias Google. No meu caso, de Android. :P
No mês de junho participei de um dos eventos de Android que eu mais gosto: o Androidos day. O evento esse ano contou com a participação de três GDEs de Android. Além de mim, o Quinta e o Bira também estavam lá e enriqueceram demais o evento com suas palestras. Sem contar os outros palestrantes que deram show lá! Parabéns Josias e demais integrantes da organização! Foi muito legal o evento.
E você que está lendo esse post, não perca a edição de 2017! ;)
A partir do mês de julho, o GDG Recife começou a fazer mensalmente meetups de Android onde participei com algumas palestras e sugerindo o conteúdo que seria apresentado. Infelizmente não consegui organizar nada para Novembro e Dezembro, mas prometo voltar com essa iniciativa em 2017.
Em Outubro teve o GDG DevFest Nordeste que foi simplesmente fodástico! O evento aconteceu em um resort em Maceió. Um lugar fenomenal, duas trilhas de conteúdo, muuuuita gente boa palestrando. Enfim, um evento memorável. Parabéns Juarez, Juninho e todos da organização! ;)
Palestrantes e organização do DevFest Nordeste
Eventos internacionais
Em maio participei mais uma vez do Google I/O. Dessa vez em Mountain View (nos outros anos foi em San Francisco) e em um local ao ar livre: o Shoreline Amphitheatre. O evento foi bem bacana, onde o pessoal apresentou todas (ou quase todas) as novidades do Google: Google Home, Alo/Duo, Tango/Daydream, Firebase, Android Wear 2.0, Android Studio 2.2, Android N, ... Enfim, foi muito foda como sempre. \o/
Eu no Google I/O
No mês de novembro, participei do GDE Summit lá no Google, em Mountain View. Esse evento é fantástico para conhecer e rever GDEs de todo mundo, pois muitos deles já trabalharam no Google ou desempenham um papel fundamental na comunidade mundial de desenvolvedores. Além é claro, de ter contato direto com o advocates e o pessoal de produto do Google. Então você pode conversar e saber mais sobre a tendências e a direção que as tecnologias do Google estão tomando. Acho que esse foi o melhor summit que já participei. Muito conteúdo, dicas, conversas e coisas novas para brincar como o Google Home, Tango e Android Things.
GDEs brasileiros no GDE Summit
Também participei do DevFest Silicon Valley. Foi legal, mas nem se compara aos nossos DevFests ;)
Certificação Android
No Google I/O desse ano, o Google anunciou uma parceria com a Udacity para elaborar uma certificação oficial para desenvolvedores Android: a Associate Android Developer. Eu fiz esse exame e escrevi esse post aqui para explicar como funciona todo o processo.
Aulas na Unibratec
Esse ano assumi apenas uma turma de pós graduação, mas que durou quase 4 meses. A coordenação da Unibratec está de parabéns por ter designado 72 horas para a disciplina de Android. Isso me permitiu trabalhar muito bem o conteúdo e foi muito enriquecedor porque a turma estava muito interessada.
Turma de pós graduação da Unibratec
E para finalizar o ano, mais uma despedida: esse será meu último semestre como professor da Unibratec. Devido a viagens que eu tenho que fazer no meu emprego atual e por precisar dedicar mais tempo a algumas outras coisas da minha carreira, tive que me desligar da Unibratec. Ainda ficarei com as turmas de pós-graduação, mas vou dar um tempo nas turmas de graduação.
--
Bem pessoal, essa foi a retrospectiva de 2016. E como vocês puderam ver, esse ano foi muito LOKO! Mas foi muito bom para mim.
Espero que 2017 seja muito bom também para nós todos.
4br4ç05,
nglauber
Primeiramente peço desculpas por não ter postado muito esse ano, mas se vocês lerem esse texto, vão entender um pouquinho o motivo. 2016 foi um ano muito intenso, com muitas mudanças que exigiram bastante de mim.
Dominando o Android 2ª edição
No começo do ano saiu a 2ª edição do meu livro, o "Dominando o Android" com uma série de correções e novos conteúdos. Muitas coisas que eu gostaria ter colocado na primeira edição entraram nessa edição e eu fiquei muito feliz com o resultado. Ainda não estou trabalhando na 3ª edição, mas creio que teremos novidades em junho ou julho de 2017.
Despedida do CESAR
Sem sombra de dúvida o evento mais marcante para mim foi minha saída do CESAR. No mês de março, após 10 anos, resolvi pedir demissão, simplesmente porque o que a instituição esperava de mim não estava alinhado com os meus objetivos profissionais. Então, ao invés de ficar reclamando pelos corredores ou fazer um trabalho mau feito, resolvi sair. Mas o CESAR estará sempre no meu coração por ser um lugar muito legal e cheio de pessoas bacanas. Tanto que, pelo menos uma vez por semana, saio de casa apenas para almoçar com amigos que trabalham ou trabalharam no CESAR :)
Equipe do projeto HP no CESAR
Mesa e Mokriya
Quando estava querendo sair do CESAR, meu amigo Leocádio Tiné me convidou para para substituí-lo lá na Mesa. Uma empresa muito bacana aqui de Recife com cerca de 12 pessoas. Então em abril comecei a trabalhar lá. O desafio era bem diferente do CESAR, onde normalmente tínhamos equipes com várias pessoas trabalhando em um mesmo projeto. A demanda de aplicativos lá era/é bem grande e cada desenvolvedor ficava responsável por fazer um app do começo ao fim. Achei isso bem bacana e isso me motivou bastante.
Equipe da Mesa
Com certeza eu ficaria na Mesa por um bom tempo, devido ao ambiente e o trabalho que eram bem legais. Mas o meu grande amigo Douglas Drummond ficou sabendo que eu tinha saído do CESAR e me convidou para entrar no processo seletivo da Mokriya, uma empresa de Cupertino onde a maioria dos funcionários trabalha remotamente. Participei do processo, fui aprovado e como a proposta foi bem interessante, tive que deixar a Mesa para trabalhar de casa, mais uma experiência nova para mim... Tenho que escrever um post sobre isso :)
Pranil, eu e Sunil. Donos da Mokriya.
Quero aproveitar para agradecer a Antônio, Arthur e Tiago que me deram essa oportunidade de fazer parte da Mesa. Infelizmente foi por pouco tempo, mas foi muito bom. E um agradecimento muito especial a Douglas por ter apostado em mim, mesmo tendo conversado pessoalmente comigo apenas duas ou três vezes. Valeu mesmo! ;)
Eventos nacionais
Em termos de eventos, esse ano eu não participei tanto, comparado aos anos anteriores.
Em parceria com o GDG Recife, pelo segundo ano consecutivo eu fui mentor do Study Jam que é uma iniciativa do Google em parceria com a Udacity para ministrar cursos gratuitos sobre tecnologias Google. No meu caso, de Android. :P
Turma do Study Jam
No mês de junho participei de um dos eventos de Android que eu mais gosto: o Androidos day. O evento esse ano contou com a participação de três GDEs de Android. Além de mim, o Quinta e o Bira também estavam lá e enriqueceram demais o evento com suas palestras. Sem contar os outros palestrantes que deram show lá! Parabéns Josias e demais integrantes da organização! Foi muito legal o evento.
E você que está lendo esse post, não perca a edição de 2017! ;)
Palestrantes e organização do Androidos
A partir do mês de julho, o GDG Recife começou a fazer mensalmente meetups de Android onde participei com algumas palestras e sugerindo o conteúdo que seria apresentado. Infelizmente não consegui organizar nada para Novembro e Dezembro, mas prometo voltar com essa iniciativa em 2017.
Em Outubro teve o GDG DevFest Nordeste que foi simplesmente fodástico! O evento aconteceu em um resort em Maceió. Um lugar fenomenal, duas trilhas de conteúdo, muuuuita gente boa palestrando. Enfim, um evento memorável. Parabéns Juarez, Juninho e todos da organização! ;)
Palestrantes e organização do DevFest Nordeste
Eventos internacionais
Em maio participei mais uma vez do Google I/O. Dessa vez em Mountain View (nos outros anos foi em San Francisco) e em um local ao ar livre: o Shoreline Amphitheatre. O evento foi bem bacana, onde o pessoal apresentou todas (ou quase todas) as novidades do Google: Google Home, Alo/Duo, Tango/Daydream, Firebase, Android Wear 2.0, Android Studio 2.2, Android N, ... Enfim, foi muito foda como sempre. \o/
Eu no Google I/O
No mês de novembro, participei do GDE Summit lá no Google, em Mountain View. Esse evento é fantástico para conhecer e rever GDEs de todo mundo, pois muitos deles já trabalharam no Google ou desempenham um papel fundamental na comunidade mundial de desenvolvedores. Além é claro, de ter contato direto com o advocates e o pessoal de produto do Google. Então você pode conversar e saber mais sobre a tendências e a direção que as tecnologias do Google estão tomando. Acho que esse foi o melhor summit que já participei. Muito conteúdo, dicas, conversas e coisas novas para brincar como o Google Home, Tango e Android Things.
GDEs brasileiros no GDE Summit
Também participei do DevFest Silicon Valley. Foi legal, mas nem se compara aos nossos DevFests ;)
Certificação Android
No Google I/O desse ano, o Google anunciou uma parceria com a Udacity para elaborar uma certificação oficial para desenvolvedores Android: a Associate Android Developer. Eu fiz esse exame e escrevi esse post aqui para explicar como funciona todo o processo.
Aulas na Unibratec
Esse ano assumi apenas uma turma de pós graduação, mas que durou quase 4 meses. A coordenação da Unibratec está de parabéns por ter designado 72 horas para a disciplina de Android. Isso me permitiu trabalhar muito bem o conteúdo e foi muito enriquecedor porque a turma estava muito interessada.
Turma de pós graduação da Unibratec
E para finalizar o ano, mais uma despedida: esse será meu último semestre como professor da Unibratec. Devido a viagens que eu tenho que fazer no meu emprego atual e por precisar dedicar mais tempo a algumas outras coisas da minha carreira, tive que me desligar da Unibratec. Ainda ficarei com as turmas de pós-graduação, mas vou dar um tempo nas turmas de graduação.
--
Bem pessoal, essa foi a retrospectiva de 2016. E como vocês puderam ver, esse ano foi muito LOKO! Mas foi muito bom para mim.
Espero que 2017 seja muito bom também para nós todos.
4br4ç05,
nglauber
sábado, 12 de novembro de 2016
Android Libs: Data Binding + Retrofit + RXJava + Retrolambda +EventBus
Olá povo,
Como estou com preguiça de escrever, estou gravando alguns vídeos com conteúdos que eu acho relevante e colocando no YouTube.
No vídeo abaixo eu mostro como dar os primeiros passos com as bibliotecas Data Binding, Retrofit, RXJava, Retrolambda e EventBus.
Data Binding
Meus slides
Post no blog
Retrofit
https://square.github.io/retrofit/
RXJava
https://github.com/ReactiveX/RxAndroid
Slides do Ubiratan:
https://speakerdeck.com/ubiratansoares/rxjava-for-android
https://speakerdeck.com/ubiratansoares/refactoring-for-rxjava
Retrolambda
https://github.com/orfjackal/retrolambda
Plugin do Gradle:
https://github.com/evant/gradle-retrolambda
EventBus
https://github.com/greenrobot/EventBus
OMDB API: http://www.omdbapi.com/
JSONViewer: http://jsonviewer.stack.hu/
Código-fonte desse exemplo:
https://github.com/nglauber/playground/tree/master/android/ProjetoFilmesLibs
Referências:
https://guides.codepath.com/android/Consuming-APIs-with-Retrofit
http://www.vogella.com/tutorials/Retrolambda/article.html
4br4ç05,
nglauber
Como estou com preguiça de escrever, estou gravando alguns vídeos com conteúdos que eu acho relevante e colocando no YouTube.
No vídeo abaixo eu mostro como dar os primeiros passos com as bibliotecas Data Binding, Retrofit, RXJava, Retrolambda e EventBus.
Data Binding
Meus slides
Post no blog
Retrofit
https://square.github.io/retrofit/
RXJava
https://github.com/ReactiveX/RxAndroid
Slides do Ubiratan:
https://speakerdeck.com/ubiratansoares/rxjava-for-android
https://speakerdeck.com/ubiratansoares/refactoring-for-rxjava
Retrolambda
https://github.com/orfjackal/retrolambda
Plugin do Gradle:
https://github.com/evant/gradle-retrolambda
EventBus
https://github.com/greenrobot/EventBus
OMDB API: http://www.omdbapi.com/
JSONViewer: http://jsonviewer.stack.hu/
Código-fonte desse exemplo:
https://github.com/nglauber/playground/tree/master/android/ProjetoFilmesLibs
Referências:
https://guides.codepath.com/android/Consuming-APIs-with-Retrofit
http://www.vogella.com/tutorials/Retrolambda/article.html
4br4ç05,
nglauber
terça-feira, 20 de setembro de 2016
Constraint Layout no Android Studio 2.2
Olá pessoal,
Com o lançamento do Android Studio 2.2, resolvi fazer um vídeo falando um pouquinho sobre o novo gerenciador de layouts do Android: o ConstraintLayout.
O vídeo é um pouquinho longo (25min) e mostra como criar um layout de uma tela do aplicativo do Netflix utilizando o ConstraintLayout no novo editor visual do Android Studio.
Como é algo relativamente novo, qualquer feedback é muito bem vindo.
Esqueci de falar no vídeo que o ConstraintLayout é compatível com o Android 2.3 e superior.
Mais informações:
Bug report:
Errata:
Qualquer dúvida, deixem seus comentários.
4br4ç05,
nglauber
Com o lançamento do Android Studio 2.2, resolvi fazer um vídeo falando um pouquinho sobre o novo gerenciador de layouts do Android: o ConstraintLayout.
O vídeo é um pouquinho longo (25min) e mostra como criar um layout de uma tela do aplicativo do Netflix utilizando o ConstraintLayout no novo editor visual do Android Studio.
Como é algo relativamente novo, qualquer feedback é muito bem vindo.
Esqueci de falar no vídeo que o ConstraintLayout é compatível com o Android 2.3 e superior.
Mais informações:
- http://android-developers.blogspot.com.br/2016/09/android-studio-2-2.html
- https://developer.android.com/training/constraint-layout/index.html
- http://tools.android.com/tech-docs/layout-editor
Bug report:
- No vídeo (4:50), podemos notar que o wrap_content não respeita as margens estipuladas. Meu amigo Diego Nascimento notou esse problema em outras situações e reportou o bug para o Google. Eu adicionei meu comentário lá e vamos aguardar o que eles vão fazer.
https://code.google.com/p/android/issues/detail?id=223308
Errata:
- No vídeo foi quando falei "Auto run" ao invés de "Instant Run".
Qualquer dúvida, deixem seus comentários.
4br4ç05,
nglauber
segunda-feira, 5 de setembro de 2016
DevFest Nordeste 2016
Olá povo,
O GDG DevFest é uma iniciativa do Google em parceira com os GDGs (Google Developer Groups) de todo o mundo para oferecer grandes eventos para a comunidade de desenvolvedores. A temporada dos DevFests acontece entre 1 de setembro e 30 de novembro, e no Brasil ele acontecerá em diversas regiões do país. No nordeste, o evento já aconteceu em Aracajú (2014), Recife (2015) e esse ano o DevFest Nordeste será realizado em Maceió-AL, nos dias 21 e 22 de outubro no Pratagy Beach Resort e contará com grandes palestrantes de várias partes do Brasil. Serão discutidos temas relacionados as tecnologias web, backend, mobile, UX e muito mais.
Eu participarei do evento com a palestra "Dominando o Data Binding no Android" onde veremos como otimizar a implementar a lógica da interface gráfica do aplicativo de forma mais fácil, rápida e menos sujeita a bugs. Para conferir a programação completa, clique aqui.
Para obter mais informações, consulte o site oficial do evento.
Você não vai perder essa oportunidade de aprender e fazer parte dessa grande comunidade de desenvolvedores, não é?
Nos vemos lá! ;)
[EDITADO 25/10/2016]
Slides da minha palestra.
4br4ç05,
nglauber
terça-feira, 30 de agosto de 2016
Certificação Android da Udacity
Olá pessoal,
No Google I/O 2016 foi anunciada a primeira certificação para desenvolvedores Android. O nome da prova é Associate Android Developer Exam e é mantida pela Udacity em parceria com o Google. O intuito dessa certificação é tornar mais fácil para empresas encontrar desenvolvedores qualificados, e obviamente, "provar" que o desenvolvedor possui o conhecimento necessário para criar aplicativos seguindo os padrões recomendados.
Por curiosidade, resolvi fazer essa prova para saber o nível de dificuldade e até orientar meus alunos e demais desenvolvedores interessados na certificação. Sendo assim, o objetivo desse post é dar meu feedback sobre essa prova.
A preparação sugerida para a prova é fazer os cursos da Udacity, que em sua maioria tem o material (vídeos) gratuitos. Mas você pode fazer os cursos de formação conhecidos como Nanodegree, que atualmente estão divididos em Android Basics e Android Developer.
O básico possui:
A avaliação é bem diferente das provas de certificação Java (Mobile, Programmer e Web) da Sun/Oracle, pois não é composta de uma série de perguntas de múltipla escolha e com um monte de "pegadinhas". Na certificação Android você recebe um projeto (bem pequeno, com cerca de 12 classes) com algum código já pronto. Então você precisa implementar funcionalidades e corrigir alguns bugs. O prazo para isso é de 48 horas, então reserve um tempo livre para fazer o exame.
Os assuntos utilizados na prova estão em um nível bem básico. São eles: criação de layouts simples, utilização da pasta de recursos, criação de adapter para RecyclerView, definição de menu, ContentProvider usando SQLite, SharedPreferences, trabalhar em background, IntentService, JobScheduler, Notification, AppWidgets e testes com Espresso. Ou seja, a prova é bem abrangente, mas não exige um profundo conhecimento desses assuntos (principalmente sobre testes). Achei interessante eles não cobrirem/pedirem nada sobre fragments.
Uma vez preparado para realizar a prova, basta se registrar e pagar a taxa. O valor é de US$149 mas, segundo a Udacity, até 31 de dezembro de 2016, o valor cobrado será de US$ 99.
Ao começar a prova, será exibida uma lista de requisitos a serem implementados na aplicação. Você terá que: alterar telas existentes, criar uma nova tela, implementar um adapter, alterar um Content Provider, executar um Service, disparar notificações, agendar serviços, corrigir alguns bugs e escrever um teste simples.
Concluído o projeto, você terá que enviá-lo em um arquivo zip (apague as pastas build e app/build), escanear um documento seu (eu usei minha CNH) e enviá-lo em formato PDF. Feito isso, será feita uma avaliação (tanto automática, quanto por pessoas) do seu projeto e você receberá o resultado para saber se seu projeto cumpre o que foi requisitado ou se precisa de modificações. Se ele cumprir todas as especificações, você irá para a fase de entrevista onde você poderá explicar como você implementou seu projeto. Pelo que sei, por enquanto a entrevista é apenas em inglês, mas parece que a Udacity já está trabalhando para fazê-la também em português. Sendo aprovado na entrevista, você receberá sua certificação. Segundo a Udacity, espera-se que todo esse processo dure no máximo 45 dias.
Ainda estou aguardando o resultado da avaliação e consequentemente a entrevista. Assim que for andando o processo, vou atualizando o post aqui.
Enfim, achei o nível da prova bem bacana para uma certificação de entrada. E acho que qualquer dev com 1 ano (ou até menos) de experiência consegue fazer.
[ATUALIZAÇÃO 27/09/2016]
Recebi um email da Udacity para “verificar minha identidade”. Basicamente eles pedem para que você envie uma foto da sua identidade/carteira de motorista/passaporte. Pode ser tirada com a webcam do computador ou escaneada. Enviei a foto do passaporte para não ter o risco de problema com “documento brasileiro”. Após enviar a foto do documento, eles pedem uma foto sua. Tirei ambas com a webcam e enviei. Minutos depois, recebi um email informando que minha identificação tinha sido confirmada com sucesso. Agora creio que a próxima etapa será a entrevista
[ATUALIZAÇÃO 17/10/2016]
Após 47 dias, ainda não recebi nenhum feedback sobre a certificação. Após dar aquela boa e velha "xingada no twitter", o JP (o cara do vídeo acima) respondeu...
Vamos ver quanto tempo demora esse "breve".
[ATUALIZAÇÃO 25/10/2016]
Eis que após 55 dias recebo o email para agendar a entrevista da Certificação Android. Tentei três datas diferentes e em todas só havia um horário disponível.
No email eles deixam bem claro que você precisará de um documento para comprovar sua identidade (passaporte ou carteira de motorista de preferência). Você precisará de uma webcam e de uma boa conexão de internet para não haver problema de comunicação na entrevista.
Fiz o agendamento para o dia 28/10 às 20h (horário de Brasília). Vamos ver como me saio :)
[ATUALIZAÇÃO 28/10/2016]
Chegou o dia da entrevista. Esqueci de mencionar na atualização anterior que no momento do agendamento, é informado o link para o aplicativo Zoom (https://zoom.us/) que você deve ter instalado na sua máquina.
Minha entrevista durou exatos 5 minutos :) isso mesmo. O camarada me deu boa-noite, pediu para eu mostrar minha identidade e disse que iria me fazer 5 perguntas. Todas extremamente fáceis e nada de mostrar ou explicar código.
Respondidas as questões, o entrevistador me deu os parabéns, disse que eu era um dos primeiros a terminar o processo e que em breve eu receberia um email com mais informações.
[ATUALIZAÇÃO 04/11/2016]
Após uma semana de espera, chegou o email da Udacity com o resultado da avaliação.
Agora tenho que aguardar outro email para pegar minha badge... :)
[ATUALIZAÇÃO 23/11/2016]
Chegou o email com a badge! Até que é bonitinha :)
No email, chegam as instruções para você adicionar a certificação no seu perfil do LinkedIn. Basicamente você clicar em um link, então o LinkedIn vai perguntar se você quer adicionar essa certificação ao seu perfil e pronto! Vai aparecer isso no seu perfil, na seção de certificações :)
Acho que esse será o último update desse post. Ciclo completo depois de 83 dias (ao contrário dos 45 prometidos pela Udacity). Espero que venham novas certificações mais exigentes e mais organizadas que essa.
[ATUALIZAÇÃO 22/11/2017]
Há um tempo atrás recebi um email da Udacity pedindo algumas informações, entre elas o tamanho de camiseta. Eis que um ano após a certificação, acabam de chegar alguns "mimos" :)
Uma camiseta, um bonequinho do Android e um adesivo. Achei bacaninha :) Valeu Google/Udacity!
4br4ç05,
nglauber
No Google I/O 2016 foi anunciada a primeira certificação para desenvolvedores Android. O nome da prova é Associate Android Developer Exam e é mantida pela Udacity em parceria com o Google. O intuito dessa certificação é tornar mais fácil para empresas encontrar desenvolvedores qualificados, e obviamente, "provar" que o desenvolvedor possui o conhecimento necessário para criar aplicativos seguindo os padrões recomendados.
Por curiosidade, resolvi fazer essa prova para saber o nível de dificuldade e até orientar meus alunos e demais desenvolvedores interessados na certificação. Sendo assim, o objetivo desse post é dar meu feedback sobre essa prova.
A preparação sugerida para a prova é fazer os cursos da Udacity, que em sua maioria tem o material (vídeos) gratuitos. Mas você pode fazer os cursos de formação conhecidos como Nanodegree, que atualmente estão divididos em Android Basics e Android Developer.
O básico possui:
Enquanto que o segundo contém:
- Developing Android Apps
- Gradle for Android
- Material Design for Android Developers
- Performance
- Advanced Android Development
A avaliação é bem diferente das provas de certificação Java (Mobile, Programmer e Web) da Sun/Oracle, pois não é composta de uma série de perguntas de múltipla escolha e com um monte de "pegadinhas". Na certificação Android você recebe um projeto (bem pequeno, com cerca de 12 classes) com algum código já pronto. Então você precisa implementar funcionalidades e corrigir alguns bugs. O prazo para isso é de 48 horas, então reserve um tempo livre para fazer o exame.
Os assuntos utilizados na prova estão em um nível bem básico. São eles: criação de layouts simples, utilização da pasta de recursos, criação de adapter para RecyclerView, definição de menu, ContentProvider usando SQLite, SharedPreferences, trabalhar em background, IntentService, JobScheduler, Notification, AppWidgets e testes com Espresso. Ou seja, a prova é bem abrangente, mas não exige um profundo conhecimento desses assuntos (principalmente sobre testes). Achei interessante eles não cobrirem/pedirem nada sobre fragments.
Uma vez preparado para realizar a prova, basta se registrar e pagar a taxa. O valor é de US$149 mas, segundo a Udacity, até 31 de dezembro de 2016, o valor cobrado será de US$ 99.
Ao começar a prova, será exibida uma lista de requisitos a serem implementados na aplicação. Você terá que: alterar telas existentes, criar uma nova tela, implementar um adapter, alterar um Content Provider, executar um Service, disparar notificações, agendar serviços, corrigir alguns bugs e escrever um teste simples.
Concluído o projeto, você terá que enviá-lo em um arquivo zip (apague as pastas build e app/build), escanear um documento seu (eu usei minha CNH) e enviá-lo em formato PDF. Feito isso, será feita uma avaliação (tanto automática, quanto por pessoas) do seu projeto e você receberá o resultado para saber se seu projeto cumpre o que foi requisitado ou se precisa de modificações. Se ele cumprir todas as especificações, você irá para a fase de entrevista onde você poderá explicar como você implementou seu projeto. Pelo que sei, por enquanto a entrevista é apenas em inglês, mas parece que a Udacity já está trabalhando para fazê-la também em português. Sendo aprovado na entrevista, você receberá sua certificação. Segundo a Udacity, espera-se que todo esse processo dure no máximo 45 dias.
Ainda estou aguardando o resultado da avaliação e consequentemente a entrevista. Assim que for andando o processo, vou atualizando o post aqui.
Enfim, achei o nível da prova bem bacana para uma certificação de entrada. E acho que qualquer dev com 1 ano (ou até menos) de experiência consegue fazer.
[ATUALIZAÇÃO 27/09/2016]
Recebi um email da Udacity para “verificar minha identidade”. Basicamente eles pedem para que você envie uma foto da sua identidade/carteira de motorista/passaporte. Pode ser tirada com a webcam do computador ou escaneada. Enviei a foto do passaporte para não ter o risco de problema com “documento brasileiro”. Após enviar a foto do documento, eles pedem uma foto sua. Tirei ambas com a webcam e enviei. Minutos depois, recebi um email informando que minha identificação tinha sido confirmada com sucesso. Agora creio que a próxima etapa será a entrevista
[ATUALIZAÇÃO 17/10/2016]
Após 47 dias, ainda não recebi nenhum feedback sobre a certificação. Após dar aquela boa e velha "xingada no twitter", o JP (o cara do vídeo acima) respondeu...
Vamos ver quanto tempo demora esse "breve".
[ATUALIZAÇÃO 25/10/2016]
Eis que após 55 dias recebo o email para agendar a entrevista da Certificação Android. Tentei três datas diferentes e em todas só havia um horário disponível.
No email eles deixam bem claro que você precisará de um documento para comprovar sua identidade (passaporte ou carteira de motorista de preferência). Você precisará de uma webcam e de uma boa conexão de internet para não haver problema de comunicação na entrevista.
Fiz o agendamento para o dia 28/10 às 20h (horário de Brasília). Vamos ver como me saio :)
[ATUALIZAÇÃO 28/10/2016]
Chegou o dia da entrevista. Esqueci de mencionar na atualização anterior que no momento do agendamento, é informado o link para o aplicativo Zoom (https://zoom.us/) que você deve ter instalado na sua máquina.
Minha entrevista durou exatos 5 minutos :) isso mesmo. O camarada me deu boa-noite, pediu para eu mostrar minha identidade e disse que iria me fazer 5 perguntas. Todas extremamente fáceis e nada de mostrar ou explicar código.
Respondidas as questões, o entrevistador me deu os parabéns, disse que eu era um dos primeiros a terminar o processo e que em breve eu receberia um email com mais informações.
[ATUALIZAÇÃO 04/11/2016]
Após uma semana de espera, chegou o email da Udacity com o resultado da avaliação.
Agora tenho que aguardar outro email para pegar minha badge... :)
[ATUALIZAÇÃO 23/11/2016]
Chegou o email com a badge! Até que é bonitinha :)
No email, chegam as instruções para você adicionar a certificação no seu perfil do LinkedIn. Basicamente você clicar em um link, então o LinkedIn vai perguntar se você quer adicionar essa certificação ao seu perfil e pronto! Vai aparecer isso no seu perfil, na seção de certificações :)
Acho que esse será o último update desse post. Ciclo completo depois de 83 dias (ao contrário dos 45 prometidos pela Udacity). Espero que venham novas certificações mais exigentes e mais organizadas que essa.
[ATUALIZAÇÃO 22/11/2017]
Há um tempo atrás recebi um email da Udacity pedindo algumas informações, entre elas o tamanho de camiseta. Eis que um ano após a certificação, acabam de chegar alguns "mimos" :)
Uma camiseta, um bonequinho do Android e um adesivo. Achei bacaninha :) Valeu Google/Udacity!
4br4ç05,
nglauber
Assinar:
Postagens (Atom)





















