Palestra realizada no DevFestXP em Recife (09/12/2017) apresentando as principais técnicas, APIs e ferramentas mais atuais utilizadas no desenvolvimento de aplicações Android
10. Porque Kotlin?
• Linguagem moderna, concisa, intuitiva e fácil de aprender.
• Open Source, mantido pela JetBrains
• 100% Inter-operável com Java. Você pode possuir código Java e
Kotlin no mesmo projeto (inclusive libs).
• Suporte nativo no Android Studio.
• Menos verboso. Você escreve menos código.
• Null Safety
• Possui recursos de linguagens funcionais
• Inferência de tipos, lambda, extension functions, high-order
functions, …
15. ConstraintLayout
• Implementa o conceito de flat layout. Melhorando a
performance.
• É um mix dos demais layouts, com mais recursos.
• É muito mais fácil criar os layout utilizando visual editor.
Mas o XML continua legível.
• É uma biblioteca separada do S.O., o que facilita a
atualização
• A adoção por parte dos desenvolvedores iOS é facilitada.
26. Activity é uma tela do seu
aplicativo…
• Ela acessa o banco de dados
• Ela acessa a web
• Ela valida campos
• Ela controla o fluxo da tela
27.
28. Pague as consequências!!!
• Código altamente acoplado
• Difícil de mante e adicionar
novas funcionalidades
• Difícil de testar,
consequentemente instável
• Resumindo: viola todos os
princípios do S.O.L.I.D.
29. Initial Stands for Concept
S SRP[4] Single responsibility principle
a class should have only a single responsibility (i.e. only one potential change
in the software's specification should be able to affect the specification of the
class)
O OCP[5] Open/closed principle
“software entities … should be open for extension, but closed for modification.”
L LSP[6] Liskov substitution principle
“objects in a program should be replaceable with instances of their subtypes
without altering the correctness of that program.” See also design by contract.
I ISP[7] Interface segregation principle
“many client-specific interfaces are better than one general-purpose
interface.”[8]
D DIP[9] Dependency inversion principle
one should “depend upon abstractions, [not] concretions.”[8]
35. Data Binding
• Facilita a ligação entre View Model e View
• Estende os arquivos de layout com micro-
expressões
• Binders customizados reduzem a repetição de
código
44. Lifecycle
• Lifecycle é um objeto que define um ciclo de vida
• LifecycleOwner é uma interface para objetos com um
ciclo de vida
• A partir da appcompat 26.1, Activity e Fragment
implementam LifecycleOwner.
• LifecycleObserver é uma interface para observar um
LifecycleOwner
45. class MyLifecycleObserver: LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun start() {
Log.d("NGVL", "onStart!!!")
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stop() {
Log.d("NGVL", "onStop!!!")
}
}
46. class YourActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_your)
val observer = MyLifecycleObserver()
lifecycle.addObserver(observer)
...
}
}
48. class ScoreViewModel: ViewModel() {
var score = Score()
fun updateTeamA() {
score.teamA++
}
fun updateTeamB() {
score.teamB++
}
fun reset(){
score.teamA = 0
score.teamB = 0
}
}
49. class MainActivity : AppCompatActivity() {
private val viewModel: ScoreViewModel by lazy {
ViewModelProviders.of(this).get(ScoreViewModel::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val score = viewModel.score
...
}
}
50. Cuidado!!!
• Não passe referências de Activities ou Fragments para o
ViewModel
• Se precisar de um Context, crie uma subclass de
AndroidViewModel que terá uma instância do contexto
da aplicação
• Se precisar passar parâmetros para o ViewModel, é preciso
criar uma subclasse de
ViewModelProvider.NewInstanceFactory
• O ViewModel não substitui o onSaveInstanceState!
51. LiveData
• LiveData armazena dados observáveis (Observable) e
notifica os observadores (Observers) quando esses dados
mudam para que a UI seja atualizada.
• O LiveData é lifecycle-aware. Ele só notificará a UI se a
Activity/Fragment estiver no estado STARTED ou
RESUMED.
52. class CharactersViewModel : ViewModel() {
val characters = MutableLiveData<List<Character>>()
fun loadCharacters() {
// Carregar dados da web...
characters.value = list
}
...
}
53. class CharactersActivity : AppCompatActivity() {
private val viewModel: CharactersViewModel /*init*/
private val adapter: CharactersAdapter /*init*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_characters)
viewModel.load()
viewModel.characters.observe(this, Observer { characters ->
adapter.setItems(characters)
})
...
}
}
54. Room
• ORM para Android sobre o SQLite.
• Suporta atualização automática da UI com LiveData ou
RXJava
57. import android.arch.persistence.room.*
@Dao
interface EventDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(event: Event): Long
@Update
fun update(event: Event): Int
@Delete
fun delete(vararg event: Event): Int
@Query("SELECT * FROM Event WHERE description LIKE :descr")
fun eventsByDescription(descr: String = "%"): List<Event>
@Query("SELECT * FROM Event WHERE id = :id")
fun eventById(id: Long): Event
}
58. import android.arch.persistence.room.*
@Dao
interface EventDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(event: Event): Long
@Update
fun update(event: Event): Int
@Delete
fun delete(vararg event: Event): Int
@Query("SELECT * FROM Event WHERE description LIKE :descr")
fun eventsByDescription(descr: String = "%"): LiveData<List<Event>>
@Query("SELECT * FROM Event WHERE id = :id")
fun eventById(id: Long): LiveData<Event>
}
60. val db = Room.databaseBuilder(applicationContext,
MyRoomDatabase::class.java, "myDb")
.build()
val dao = db.eventDao()
val event = Event(0, "DevFestXP", "DevFest Recife 2017")
val id = dao.insert(event)
val event2 = dao.eventById(id)
Log.d("NGVL", "${event2.id} ${event2.name} - ${event2.description}")
val events = dao.eventsByDescription()
events.forEach {
Log.d("NGVL", "${it.id} ${it.name} - ${it.description}")
}
66. RX Java
RxJava é uma biblioteca que permite representar
qualquer operação como um fluxo assíncrono de
dados criado por qualquer thread, de forma declarativa
e consumida por múltiplos objetos em várias threads.
79. • Você não precisa usar todos esses
recursos no mesmo app…
• Na verdade, você não precisa usar
nenhum!
• Mais importante do que saber quando
USAR é saber quando NÃO USAR 😉
• Mas é essencial conhecer tópicos,
saber seus prós e contras e utilizá-los
adequadamente 💡
80. Um desenvolvedor
moderno…
1. Faça parte da comunidade!!!
2. Kotlin como linguagem de programação
3. Constraint Layout para criação de UI
4. Uma boa arquitetura na camada de apresentação. Com MVP ou
MVVM (por exemplo)
5. Multi-threading
6. Firebase como serviço de cloud
7. Testes para garantir a estabilidade do código