Upload
luiz-henrique-santana
View
458
Download
4
Embed Size (px)
Citation preview
- Java 8 no Android N
- Streams - API level 23 ou RxJava
- Lambdas, referências à métodos, non-capturing - API level 23 ou Retrolambda
- Try with resources - API level 19 ou Retrolambda
- Métodos default em interfaces - API level 23
Android Moderninho
- Não dá pra adicionar métodos à tipos existentes - *Util em todo lugar
- Nulls - NPEs em todo lugar
- Java é verboso
- APIs do Android são complexas - Herança e nulls em todo lugar
Limitações do Java no Android
fun welcome(name: String, event: String): String { return "Hello ${name}, welcome to ${event}!" }
Functions
fun main(args: Array<String>) { val greeting = welcome("André", "TDC") println(greeting) greeting = welcome("Luiz", "TDC") println(greeting)}
Variáveis
fun main(args: Array<String>) { var greeting = welcome("André", "TDC") println(greeting) greeting = welcome("Luiz", "TDC") println(greeting)}
Variáveis
fun welcome(name: String, event: String = "TDC") = "Hello ${name}, welcome to ${event}!"
Parâmetros Default
fun main(args: Array<String>) { val greeting = welcome("André") println(greeting)}
Parâmetros Default
fun main(args: Array<String>) { val greeting = welcome(name = "Luiz", event = "I/O") println(greeting)}
Parâmetros Default
fun welcome(name: String = "Developer", event: String = "TDC") = "Hello ${name}, welcome to ${event}!"
Parâmetros Default
fun main(args: Array<String>) { val greeting = welcome(event = “Android Meetup") println(greeting)}
Parâmetros Default
val lyrics = """ |Jamais a natureza |Reuniu tanta beleza |Jamais algum poeta |Teve tanto pra cantar! “"".trimMargin() println(lyrics) val month = "(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)"var datePattern = """\d{2} ${month} \d{4}"""val today = "13 MAY 2016".matches(Regex(datePattern))println(today)
String Templates
val famousPeople = arrayListOf<String>("Einstein", "Newton", "MC Biel") val forSure = famousPeople is java.util.ArrayListprintln(forSure)
Collections
val famousPeople = arrayListOf<String>("Einstein", "Newton", "MC Bin Laden") val pairs = famousPeople.map { Pair(it, it == "MC Bin Laden") } pairs.forEach { val (name, singer) = it val verb = if (singer) "is" else "is not" println("${name} ${verb} a singer") }
Lambdas
pairs.forEach { val (name, singer) = it val verb = if (singer) "is" else "is not" println("${name} ${verb} a singer") }
Destructors e if expressions
val famousPeople = arrayListOf<String>("Einstein", "Newton", "MC Bin Laden") famousPeople.forEach { val verb = if (it.isSinger()) "is" else "is not" println("${it} ${verb} a singer") }
Extension Functions
fun SQLiteDatabase.transaction(code: SQLiteDatabase.() -> Unit) { try { beginTransaction() code() setTransactionSuccessful() } catch (e: TransactionAbortException) { // Do nothing, just stop the transaction } finally { endTransaction() }} fun SQLiteDatabase.delete(tableName: String, whereClause: String = "", vararg args: Pair<String, Any>): Int { …}
Extension Functions
fun sendEmailToClient(client: Client?, message: String?, mailer: Mailer) { val email = client?.personalInfo?.email ?: "[email protected]" if (message != null) { mailer.sendMessage(email, message) }}
Tipos Null
fun sendEmailToClient(client: Client?, message: String?, mailer: Mailer) { val email = client?.personalInfo?.email ?: "[email protected]" if (message != null) { mailer.sendMessage(email, message) }}
Null Safe Calls
fun sendEmailToClient(client: Client?, message: String?, mailer: Mailer) { val email = client?.personalInfo?.email ?: "[email protected]" if (message != null) { mailer.sendMessage(email, message) }}
Elvis
fun sendEmailToClient(client: Client?, message: String?, mailer: Mailer) { val email = client?.personalInfo?.email ?: "[email protected]" if (message != null) { mailer.sendMessage(email, message) }}
Smart Cast
fun eval(expr: Expr): Int = when (expr) { is Num -> expr.value is Sum -> eval(expr.left) + eval(expr.right) else -> throw IllegalArgumentException("Unknown expression") }interface Exprclass Num(val value: Int) : Exprclass Sum(val left: Expr, val right: Expr) : Expr
Smart Cast
class Person constructor(name: String) {} class Singer(name: String, isSinger: Boolean) : Person(name) {}
Classes
open class Person constructor(name: String) {} class Singer(name: String, isSinger: Boolean) : Person(name) {}
Classes
open class Person constructor(name: String) { open fun walk() { println("walking as a normal person") }} class Singer(name: String, isSinger: Boolean) : Person(name) { override fun walk() { println("walking with some style") }}
Classes
interface Funk { var views: Long fun funk() { views++ println("ta tranquilo ta favorável") }}
class Singer(name: String, isSinger: Boolean, override var views: Long) : Funk
Interfaces
fun main(args: Array<String>) { val mc = Singer("MC Bin Laden", true) mc.funk() mc.walk()}
Interfaces
interface Moveable { fun move() { print("move") }} interface Walkable { fun move() { walk() } fun walk() { print("walk") }} class Human : Moveable, Walkable { override fun move() { super<Walkable>.move() }}
Interfaces - Resolução de conflitos
data class Singer(val name: String, val isSinger: Boolean, override var views: Long) : Funk
fun main(args: Array<String>) { val mc = Singer("MC Bin Laden", isSinger = true, views = 10000000) println(mc.toString()) println(mc.hashCode()) println(mc.copy(name = "Catra")) }
Singer(name=MC Bin Laden, isSinger=true, views=10000001) -117390027 Singer(name=Catra, isSinger=true, views=10000001)
Data class
class Panelist { val presentation : String by lazy { "Kotlin!!!!" } var numberOfQuestions : Int by Delegates.observable(0) { prop, old, new -> println("It was ${old} not it is ${new}") } }
Delegated properties
CRIANDO O APP | OBJETIVO
- Criar um app em Kotlin
- Consumir dados MOCK, simulando “News feed” do Reddit
apply plugin: 'com.android.application'apply plugin: 'kotlin-android'android { … sourceSets { main.java.srcDirs += 'src/main/kotlin' }}dependencies {
… compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"}buildscript { ext.kotlin_version = '1.0.1-2' repositories { mavenCentral() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" }}
build.gradle
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new OnClickListener(…) {
…
}); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; }
…
}
MainActivity.java
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val toolbar = findViewById(R.id.toolbar) as Toolbar? setSupportActionBar(toolbar) val fab = findViewById(R.id.fab) as FloatingActionButton? fab?.setOnClickListener({ view -> Snackbar.make(view, "Replace with your own
action", Snackbar.LENGTH_LONG).setAction("Action", null).show() }) } override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_main, menu) return true }
…}
MainActivity.kt
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)
{ super.onCreate(savedInstanceState) setContentView(R.layout.activity_main)
…
MainActivity.kt
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)
{ super.onCreate(savedInstanceState) setContentView(R.layout.activity_main)
…
MainActivity.kt
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)
{ super.onCreate(savedInstanceState) setContentView(R.layout.activity_main)
…
MainActivity.kt
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)
{ super.onCreate(savedInstanceState) setContentView(R.layout.activity_main)
…
MainActivity.kt
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)
{ super.onCreate(savedInstanceState) setContentView(R.layout.activity_main)
…
MainActivity.kt
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val toolbar = findViewById(R.id.toolbar) as Toolbar? setSupportActionBar(toolbar) val fab = findViewById(R.id.fab) as FloatingActionButton? fab?.setOnClickListener({ view -> Snackbar.make(view, "Replace with your own
action", Snackbar.LENGTH_LONG).setAction("Action", null).show() }) } override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_main, menu) return true }
…}
MainActivity.kt
class MainActivity : AppCompatActivity() { … val toolbar = findViewById(R.id.toolbar) as Toolbar? setSupportActionBar(toolbar) val fab = findViewById(R.id.fab) as FloatingActionButton? fab?.setOnClickListener( { view -> Snackbar.make(view, "Replace with your own
action", Snackbar.LENGTH_LONG).setAction("Action", null).show() }) }
…}
MainActivity.kt
class MainActivity : AppCompatActivity() { … val toolbar = findViewById(R.id.toolbar) as Toolbar? setSupportActionBar(toolbar) val fab = findViewById(R.id.fab) as FloatingActionButton? fab?.setOnClickListener( { view -> Snackbar.make(view, "Replace with your own
action", Snackbar.LENGTH_LONG).setAction("Action", null).show() }) }
…}
MainActivity.kt
class MainActivity : AppCompatActivity() { … val toolbar = findViewById(R.id.toolbar) as Toolbar? setSupportActionBar(toolbar) val fab = findViewById(R.id.fab) as FloatingActionButton? fab?.setOnClickListener( { view -> Snackbar.make(view, "Replace with your own
action", Snackbar.LENGTH_LONG).setAction("Action", null).show() }) }
…}
MainActivity.kt
class MainActivity : AppCompatActivity() { … val toolbar = findViewById(R.id.toolbar) as Toolbar? setSupportActionBar(toolbar) val fab = findViewById(R.id.fab) as FloatingActionButton? fab?.setOnClickListener( { view -> Snackbar.make(view, "Replace with your own
action", Snackbar.LENGTH_LONG).setAction("Action", null).show() }) }
…}
MainActivity.kt
class MainActivity : AppCompatActivity() { … val toolbar = findViewById(R.id.toolbar) as Toolbar? setSupportActionBar(toolbar) val fab = findViewById(R.id.fab) as FloatingActionButton? fab?.setOnClickListener( { view -> Snackbar.make(view, "Replace with your own
action", Snackbar.LENGTH_LONG).setAction("Action", null).show() }) }
…}
MainActivity.kt
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val toolbar = findViewById(R.id.toolbar) as Toolbar? setSupportActionBar(toolbar) val fab = findViewById(R.id.fab) as FloatingActionButton? fab?.setOnClickListener({ view -> Snackbar.make(view, "Replace with your own
action", Snackbar.LENGTH_LONG).setAction("Action", null).show() }) } override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_main, menu) return true }
…}
MainActivity.kt
FRAGMENT | LAYOUT
- Criando um layout Simples<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android=“….” android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/news_list" android:layout_width="wrap_content" android:layout_height="wrap_content"> </android.support.v7.widget.RecyclerView>
</RelativeLayout>
FRAGMENT | KOTLIN CODE
class NewsFragment : Fragment() {
private var newsList: RecyclerView? = null override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater?.inflate(R.layout.fragment_news, container, false) newsList = view?.findViewById(R.id.news_list) as RecyclerView? newsList?.setHasFixedSize(true) newsList?.layoutManager = LinearLayoutManager(context) return view }}
FRAGMENT | KOTLIN CODE
class NewsFragment : Fragment() {
private var newsList: RecyclerView? = null override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater?.inflate(R.layout.fragment_news, container, false) newsList = view?.findViewById(R.id.news_list) as RecyclerView? newsList?.setHasFixedSize(true) newsList?.layoutManager = LinearLayoutManager(context) return view }}
Como melhoraro código?
EXTENSION FUNCTIONS | INFLATE
Como fazer o código abaixo ficar mais intuitivo?
… val view = inflater?.inflate(R.layout.fragment_news, container, false) …
… val view = container?.inflate(R.layout.fragment_news) …
EXTENSION FUNCTIONS | INFLATE
Como implementar?
// ExtensionsKt.ktfun ViewGroup.inflate(layoutId : Int) : View { return LayoutInflater.from(context).inflate(layoutId, this, false)}
EXTENSION FUNCTIONS | INFLATE
Reuso do código
// JavaExtensionsKt.inflate(container, R.layout.news_fragment);
// Kotlin container?.inflate(R.layout.fragment_news)
@file:JvmName("ExtensionsUtils")package com.arctouch.kotlin.commons.extensions…// Usar assim em Java:
ExtensionsUtils.inflate(container, R.layout.news_fragment);
EXTENSION FUNCTIONS | INFLATE
Parâmetros com valor padrão
fun ViewGroup.inflate(layoutId : Int, attachToRoot : Boolean = false) : View { return LayoutInflater.from(context).inflate(layoutId, this, attachToRoot)}// usar assim
val view = container?.inflate(R.layout.fragment_news) // default: false
// ou assimval view = container?.inflate(R.layout.fragment_news, true)
ANDROID EXTENSIONS | ADICIONANDO
apply plugin: 'com.android.application'apply plugin: 'kotlin-android'apply plugin: 'kotlin-android-extensions'
Adicionar no build.gradle
ANDROID EXTENSIONS | FUNCIONALIDADE
- Voltando ao Layout do Fragment…<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android=“….” android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/news_list" android:layout_width="wrap_content" android:layout_height="wrap_content"> </android.support.v7.widget.RecyclerView>
</RelativeLayout>
ANDROID EXTENSIONS | FUNCIONALIDADE
// importar no código
// import kotlinx.android.synthetic.<MODULO>.<VIEW>.*
import kotlinx.android.synthetic.main.fragment_news.*
// código antigonewsList = view?.findViewById(R.id.news_list) as RecyclerView? newsList?.setHasFixedSize(true)newsList?.layoutManager = LinearLayoutManager(context)// código novonews_list.setHasFixedSize(true)news_list.layoutManager = LinearLayoutManager(context)
LAZY PROPERTIES | INTRO
private val newsList by lazy { news_list}
override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) newsList.setHasFixedSize(true) // Executado de maneira Lazy newsList.layoutManager = LinearLayoutManager(context) }}
CRIANDO ADAPTER | INICIO
- Usaremos padrão DelegateAdapter - A ideia é ter diferentes tipos de view
num mesmo adapter - Neste caso teremos algo parecido com:
CRIANDO ADAPTER | ESTRUTURA
- Cada ViewItem possui um ViewType
enum class ViewType { LOADING, NEWS}
interface ViewDelegate { fun getType() : ViewType}
CRIANDO ADAPTER | O ADAPTER
- Nosso NewsAdapter class NewsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { private val items: ArrayList<ViewItem> = ArrayList()
// outros métodos…}
CRIANDO ADAPTER | O ADAPTER
- Nosso NewsAdapter class NewsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { private val items: ArrayList<ViewItem> = ArrayList() private val delegateAdapters: HashMap<ViewType, ViewTypeDelegateAdapter> = HashMap()
// outros métodos…}
CRIANDO ADAPTER | O ADAPTER
- Nosso NewsAdapter class NewsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { private val items: ArrayList<ViewItem> = ArrayList() private val delegateAdapters: HashMap<ViewType, ViewTypeDelegateAdapter>
= HashMap() init { delegateAdapters.put(ViewType.LOADING, LoadingDelegateAdapter()) }
// outros métodos… }
CRIANDO ADAPTER | O ADAPTER
- Nosso NewsAdapter class NewsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { private val items: ArrayList<ViewItem> = ArrayList() private val delegateAdapters: HashMap<ViewType, ViewTypeDelegateAdapter> = HashMap() private val loadingItem = object : ViewItem { override fun getType() : ViewType = ViewType.LOADING } init { delegateAdapters.put(ViewType.LOADING, LoadingDelegateAdapter()) items.add(loadingItem) }
// outros métodos…}
DATA CLASSES | MODEL
- Clássico Java model
public class RedditNewsItem { private String author; private String title; public RedditNewsItem(String author, String title) { this.author = author; this.title = title; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; }}
DATA CLASSES | MODEL
- Kotlin data class
data class RedditNewsItem(var author: String, var title: String)
Java Model + equals/hashCode toString copy
DELEGATE ADAPTERS | ESTRUTURA
- Criando estrutura inicial
interface ViewTypeDelegateAdapter { fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: ViewType)}
DELEGATE ADAPTERS | LOADING
LoadingDelegateAdapter.kt
class LoadingDelegateAdapter : ViewTypeDelegateAdapter { override fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder = SpinnerViewHolder(parent) override fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: ViewType) { } class SpinnerViewHolder(parent : ViewGroup) : RecyclerView.ViewHolder (parent.inflate(R.layout.news_item_loading)) { // infla layout em cima do pai }}
DELEGATE ADAPTERS | LOADING
LoadingDelegateAdapter.kt
class LoadingDelegateAdapter : ViewTypeDelegateAdapter { override fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder = SpinnerViewHolder(parent) override fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: ViewType) { } class SpinnerViewHolder(parent : ViewGroup) : RecyclerView.ViewHolder (parent.inflate(R.layout.news_item_loading)) { // infla layout em cima do pai }}
DELEGATE ADAPTERS | LOADING
LoadingDelegateAdapter.kt
class LoadingDelegateAdapter : ViewTypeDelegateAdapter { override fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder = SpinnerViewHolder(parent) override fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: ViewType) { } class SpinnerViewHolder(parent : ViewGroup) : RecyclerView.ViewHolder (parent.inflate(R.layout.news_item_loading)) { // infla layout em cima do pai }}
DELEGATE ADAPTERS | LOADING
LoadingDelegateAdapter.kt
class LoadingDelegateAdapter : ViewTypeDelegateAdapter { override fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder = SpinnerViewHolder(parent) override fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: ViewType) { } class SpinnerViewHolder(parent : ViewGroup) : RecyclerView.ViewHolder (parent.inflate(R.layout.news_item_loading)) { // infla layout em cima do pai }}
DELEGATE ADAPTERS | LOADING
LoadingDelegateAdapter.kt
class LoadingDelegateAdapter : ViewTypeDelegateAdapter { override fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder = SpinnerViewHolder(parent) override fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: ViewType) { } class SpinnerViewHolder(parent : ViewGroup) : RecyclerView.ViewHolder (parent.inflate(R.layout.news_item_loading)) { // infla layout dentro do container pai }}
DELEGATE ADAPTERS | NEWS
NewsDelegateAdapter.kt
class NewsAdapterDelegate : ViewTypeDelegateAdapter { override fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder = NewsViewHolder(parent) override fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: ViewItem) { holder as NewsViewHolder holder.bind(item as RedditNewsItem) } class NewsViewHolder(parent : ViewGroup) : RecyclerView.ViewHolder (parent.inflate(R.layout.news_item_loading)) { fun bind(item : RedditNewsItem) = with(itemView) { img_thumbnail.loadImgUrl(item.thumbnail) description.text = item.title author.text = item.author comments.text = "${item.commentsNumber} comments" } }}
DELEGATE ADAPTERS | NEWS
NewsDelegateAdapter.kt
class NewsAdapterDelegate : ViewTypeDelegateAdapter { override fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder = NewsViewHolder(parent) override fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: ViewItem) { holder as NewsViewHolder holder.bind(item as RedditNewsItem) } class NewsViewHolder(parent : ViewGroup) : RecyclerView.ViewHolder (parent.inflate(R.layout.news_item_loading)) { fun bind(item : RedditNewsItem) = with(itemView) { img_thumbnail.loadImgUrl(item.thumbnail) description.text = item.title author.text = item.author comments.text = "${item.commentsNumber} comments" } }}
DELEGATE ADAPTERS | NEWS
NewsDelegateAdapter.kt
class NewsAdapterDelegate : ViewTypeDelegateAdapter { override fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder = NewsViewHolder(parent) override fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: ViewItem) { holder as NewsViewHolder holder.bind(item as RedditNewsItem) } class NewsViewHolder(parent : ViewGroup) : RecyclerView.ViewHolder (parent.inflate(R.layout.news_item_loading)) { fun bind(item : RedditNewsItem) = with(itemView) { img_thumbnail.loadImgUrl(item.thumbnail) description.text = item.title author.text = item.author comments.text = "${item.commentsNumber} comments" } }}
Smart cast
DELEGATE ADAPTERS | NEWS
NewsDelegateAdapter.kt
class NewsAdapterDelegate : ViewTypeDelegateAdapter { override fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder = NewsViewHolder(parent) override fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: ViewItem) { holder as NewsViewHolder holder.bind(item as RedditNewsItem) } class NewsViewHolder(parent : ViewGroup) : RecyclerView.ViewHolder (parent.inflate(R.layout.news_item_loading)) { fun bind(item : RedditNewsItem) = with(itemView) { img_thumbnail.loadImgUrl(item.thumbnail) description.text = item.title author.text = item.author comments.text = "${item.commentsNumber} comments" } }}
DELEGATE ADAPTERS | NEWS
- Carregando imagem no bind - Extension functions
fun ImageView.loadImgUrl(imageUrl: String?) { if (imageUrl.isNullOrEmpty()) { Picasso.with(context).load(R.mipmap.ic_launcher).into(this) } else { Picasso.with(context).load(imageUrl).into(this) }}
ADICIONANDO ALGUNS DADOS MOCKclass NewsFragment : Fragment() { // … override fun onActivityCreated(savedInstanceState: Bundle?) { // … val newsAdapter = NewsAdapter() newsList.adapter = newsAdapter if (savedInstanceState == null) { newsAdapter.addNews(mockData()) } } private fun mockData() : List<RedditNewsItem> { val news = mutableListOf<RedditNewsItem>() for (i in 1..10) { news.add(RedditNewsItem( "Author $i", "Title $i", "http://lorempixel.com/200/200/technics/$i", // thumbnail i // number of comments )) } return news }}
ADICIONANDO ALGUNS DADOS MOCK
class NewsFragment : Fragment() { // … override fun onActivityCreated(savedInstanceState: Bundle?) { // … val newsAdapter = NewsAdapter() newsList.adapter = newsAdapter if (savedInstanceState == null) { newsAdapter.addNews(mockData()) } }}
ADICIONANDO ALGUNS DADOS MOCK
class NewsFragment : Fragment() { // … override fun onActivityCreated(savedInstanceState: Bundle?) { // … val newsAdapter = NewsAdapter() newsList.adapter = newsAdapter if (savedInstanceState == null) { newsAdapter.addNews(mockData()) } }}
ADICIONANDO ALGUNS DADOS MOCKclass NewsFragment : Fragment() { // … override fun onActivityCreated(savedInstanceState: Bundle?) { // … val newsAdapter = NewsAdapter() newsList.adapter = newsAdapter if (savedInstanceState == null) { newsAdapter.addNews(mockData()) } } private fun mockData() : List<RedditNewsItem> { val news = mutableListOf<RedditNewsItem>() for (i in 1..10) { news.add(RedditNewsItem( "Author $i", "Title $i", "http://lorempixel.com/200/200/technics/$i", // thumbnail i // number of comments )) } return news }}
ADICIONANDO ALGUNS DADOS MOCK
class NewsFragment : Fragment() { // … private fun mockData() : List<RedditNewsItem> { val news = mutableListOf<RedditNewsItem>() for (i in 1..10) { news.add(RedditNewsItem( "Author $i", "Title $i", "http://lorempixel.com/200/200/technics/$i", // thumbnail i // number of comments )) } return news }}
ADICIONANDO ALGUNS DADOS MOCK
class NewsFragment : Fragment() { // … private fun mockData() : List<RedditNewsItem> { val news = mutableListOf<RedditNewsItem>() for (i in 1..10) { news.add(RedditNewsItem( "Author $i", "Title $i", "http://lorempixel.com/200/200/technics/$i", // thumbnail i // number of comments )) } return news }}
ADICIONANDO ALGUNS DADOS MOCK
class NewsFragment : Fragment() { // … private fun mockData() : List<RedditNewsItem> { val news = mutableListOf<RedditNewsItem>() for (i in 1..10) { news.add(RedditNewsItem( "Author $i", "Title $i", "http://lorempixel.com/200/200/technics/$i", // thumbnail i // number of comments )) } return news }}
OUTRAS DICAS | OPTION MENU
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.action_settings -> consume { navigateToSettings() }
R.id.nav_camera -> drawer.consume { navigateToCamera() }
R.id.nav_gallery -> drawer.consume { loadGallery() }
R.id.nav_slideshow -> drawer.consume { loadSlideshow() }
else -> super.onOptionsItemSelected(item)
}
OUTRAS DICAS | OPTION MENU
inline fun consume(f: () -> Unit): Boolean {
f()
return true
}
inline fun DrawerLayout.consume(f: () -> Unit): Boolean {
f()
closeDrawers()
return true
}
OUTRAS DICAS | LAMBDAS
view.postDelayed({ doWhatever() }, 200)
Thread().run {
// Running in a thread
}
OUTRAS DICAS | COLLECTIONS
return parsedContacts.filter { it.name != null && it.image != null }
.sortedBy { it.name }
.map { Contact(it.id, it.name!!, it.image!!) }
OUTRAS DICAS | ANKO - DSL
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)
verticalLayout { padding = dip(30) editText { hint = "Name" textSize = 24f } editText { hint = "Password" textSize = 24f } button("Login") { textSize = 26f // usando tamanho em SP } } }
OUTRAS DICAS | ANKO - Useful Helpers
- Fazer ligação makeCall(numeroTelefone)
- Abrir browser browse(url)- Compartilha texto share(text, [assunto])- Enviar email email(email, [assunto], [texto])- Abrir activity startActivity<SomeOtherActivity>("id" to 5)
OUTRAS DICAS | ANKO - Useful Helpers
async() {
// Faz algo em background
uiThread {
// Volta para main thread
}
}