Slide 1

Slide 1 text

THE FUTURE IS NOW KOTLIN FOR ANDROID

Slide 2

Slide 2 text

ANTONIO LEIVA

Slide 3

Slide 3 text

ANTONIO LEIVA devexperto.com .com antonioleiva

Slide 4

Slide 4 text

DATA CLASSES JAVA public class Artist {
 private long id;
 private String name;
 private String url;
 private String mbid;
 
 public long getId() {
 return id;
 }
 
 public void setId(long id) {
 this.id = id;
 }
 
 public String getName() {
 return name;
 }
 
 public void setName(String name) {
 this.name = name;
 }
 
 public String getUrl() {
 return url;
 }
 
 public void setUrl(String url) {
 this.url = url;
 }
 
 public String getMbid() {
 return mbid;
 }
 
 public void setMbid(String mbid) {
 this.mbid = mbid;
 }
 
 @Override public String toString() {
 return "Artist{" +
 "id=" + id +
 ", name='" + name + '\'' +
 ", url='" + url + '\'' +
 ", mbid='" + mbid + '\'' +
 '}';
 }
 
 @Override public boolean equals(Object o) {
 if (this == o) return true;
 if (o == null || getClass() != o.getClass()) return false;
 
 Artist artist = (Artist) o;
 
 if (id != artist.id) return false;
 if (!name.equals(artist.name)) return false;
 if (!url.equals(artist.url)) return false;
 return mbid.equals(artist.mbid);
 
 }
 
 @Override public int hashCode() {
 int result = (int) (id ^ (id >>> 32));
 result = 31 * result + name.hashCode();
 result = 31 * result + url.hashCode();
 result = 31 * result + mbid.hashCode();
 return result;
 }
 }

Slide 5

Slide 5 text

DATA CLASSES KOTLIN data class Artist(
 var id: Long,
 var name: String,
 var url: String,
 var mbid: String)
 ▸ Getters & Setters ▸ ToString ▸ Equals & hashcode ▸ Copy ▸ Destructuring functions

Slide 6

Slide 6 text

DATA CLASSES KOTLIN data class Artist(
 var id: Long,
 var name: String,
 var url: String,
 var mbid: String)
 ▸ Getters & Setters ▸ ToString ▸ Equals & hashcode ▸ Copy ▸ Destructuring functions val artist = Artist(...)
 val (id, name, url, mbid) = artist

Slide 7

Slide 7 text

DATA CLASSES KOTLIN data class Artist(
 var id: Long,
 var name: String,
 var url: String,
 var mbid: String)
 val artist = Artist(...)
 val (id, _, url, _) = artist ▸ Getters & Setters ▸ ToString ▸ Equals & hashcode ▸ Copy ▸ Destructuring functions

Slide 8

Slide 8 text

EXTEND THE FRAMEWORK JAVA public class Utils {
 
 public static void toast(Context context, String message) {
 Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
 }
 } @Override protected void onCreate(@Nullable Bundle savedInstanceState) {
 …
 Utils.toast(this, "This is a toast");
 }

Slide 9

Slide 9 text

EXTEND THE FRAMEWORK KOTLIN fun Context.toast(message: String){
 Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
 } override fun onCreate(savedInstanceState: Bundle?) {
 …
 toast("This is a toast")
 }

Slide 10

Slide 10 text

DEFAULT VALUES FOR ARGUMENTS JAVA public class Utils {
 
 public static void toast(Context context, String message) {
 toast(context, message, Toast.LENGTH_SHORT);
 }
 
 public static void toast(Context context, String message, int length) {
 Toast.makeText(context, message, length).show();
 }
 }

Slide 11

Slide 11 text

DEFAULT VALUES FOR ARGUMENTS KOTLIN fun Context.toast(message: String, length: Int = Toast.LENGTH_SHORT){
 Toast.makeText(this, message, length).show()
 } override fun onCreate(savedInstanceState: Bundle?) {
 …
 toast("This is a toast")
 toast("This is a long toast", Toast.LENGTH_LONG)
 } extensions.kt MainActivity.kt

Slide 12

Slide 12 text

DEFAULT VALUES FOR ARGUMENTS KOTLIN USED IN JAVA ExtensionsKt.toast(this, "This is a toast");
 ExtensionsKt.toast(this, "This is a long toast", Toast.LENGTH_LONG); MyJavaActivity.java

Slide 13

Slide 13 text

DEFAULT VALUES FOR ARGUMENTS KOTLIN USED IN JAVA ExtensionsKt.toast(this, "This is a toast");
 ExtensionsKt.toast(this, "This is a long toast", Toast.LENGTH_LONG); @JvmOverloads fun Context.toast(…){
 Toast.makeText(this, message, length).show()
 } MyJavaActivity.java extensions.kt

Slide 14

Slide 14 text

DEFAULT VALUES FOR ARGUMENTS KOTLIN USED IN JAVA ExtensionsKt.toast(this, "This is a toast");
 ExtensionsKt.toast(this, "This is a long toast", Toast.LENGTH_LONG); @JvmOverloads fun Context.toast(…){
 Toast.makeText(this, message, length).show()
 } MyJavaActivity.java extensions.kt

Slide 15

Slide 15 text

CUSTOM VIEWS JAVA public class JavaView extends View {
 
 public JavaView(Context context) {
 this(context, null);
 }
 
 public JavaView(Context context, @Nullable AttributeSet attrs) {
 this(context, attrs, 0);
 }
 
 public JavaView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr); …
 }
 }

Slide 16

Slide 16 text

CUSTOM VIEWS KOTLIN class KotlinView : View { 
 constructor(context: Context) : this(context, null)
 
 constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
 
 constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
 super(context, attrs, defStyleAttr) { …
 
 }
 }

Slide 17

Slide 17 text

CUSTOM VIEWS KOTLIN class KotlinView(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) 
 : View(context, attrs, defStyleAttr)

Slide 18

Slide 18 text

CUSTOM VIEWS KOTLIN class KotlinView @JvmOverloads constructor(
 context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
 ) : View(context, attrs, defStyleAttr)

Slide 19

Slide 19 text

CUSTOM VIEWS KOTLIN

Slide 20

Slide 20 text

LAMBDAS JAVA button.setOnClickListener(new View.OnClickListener() {
 @Override public void onClick(View v) {
 …
 }
 });

Slide 21

Slide 21 text

LAMBDAS KOTLIN button.setOnClickListener { … }

Slide 22

Slide 22 text

EXTENSIONS + LAMBDAS

Slide 23

Slide 23 text

EXTENSIONS + LAMBDAS JAVA setFabAutoHideEnabled(false);
 fab.hide(new FloatingActionButton.OnVisibilityChangedListener() {
 @Override public void onHidden(FloatingActionButton fab) {
 … 
 setFabAutoHideEnabled(true);
 }
 }); private void setFabAutoHideEnabled(FloatingActionButton fab, boolean enabled) {
 CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
 FloatingActionButton.Behavior behavior = (FloatingActionButton.Behavior) lp.getBehavior();
 if (behavior != null) {
 behavior.setAutoHideEnabled(enabled);
 }
 }

Slide 24

Slide 24 text

EXTENSIONS + LAMBDAS JAVA private void hideFab(FloatingActionButton fab, final Runnable runnable) { setFabAutoHideEnabled(false);
 fab.hide(new FloatingActionButton.OnVisibilityChangedListener() {
 @Override public void onHidden(FloatingActionButton fab) {
 runnable.run();
 setFabAutoHideEnabled(true);
 }
 });
 }

Slide 25

Slide 25 text

EXTENSIONS + LAMBDAS JAVA private void hideFab(FloatingActionButton fab, final Runnable runnable) { setFabAutoHideEnabled(false);
 fab.hide(new FloatingActionButton.OnVisibilityChangedListener() {
 @Override public void onHidden(FloatingActionButton fab) {
 runnable.run();
 setFabAutoHideEnabled(true);
 }
 });
 } hideFab(fab, new Runnable() {
 @Override public void run() {
 …
 }
 });

Slide 26

Slide 26 text

EXTENSIONS + LAMBDAS KOTLIN fab.getBehaviour()?.isAutoHideEnabled = false fun FloatingActionButton.getBehaviour(): FloatingActionButton.Behavior? {
 val lp = layoutParams as? CoordinatorLayout.LayoutParams
 return lp?.behavior as? FloatingActionButton.Behavior
 }

Slide 27

Slide 27 text

EXTENSIONS + LAMBDAS KOTLIN fun FloatingActionButton.hideCarefully(f: () -> Unit) {
 getBehaviour()?.isAutoHideEnabled = false
 hide(object : FloatingActionButton.OnVisibilityChangedListener() {
 override fun onHidden(fab: FloatingActionButton) {
 f()
 getBehaviour()?.isAutoHideEnabled = true
 }
 })
 } fab.hideCarefully {
 ...
 }

Slide 28

Slide 28 text

EXTENDED PROPERTY KOTLIN fun FloatingActionButton.getBehaviour(): FloatingActionButton.Behavior? {
 … }

Slide 29

Slide 29 text

EXTENDED PROPERTY KOTLIN fun FloatingActionButton.getBehaviour(): FloatingActionButton.Behavior? {
 … } val FloatingActionButton.behavior: FloatingActionButton.Behavior?
 get() {
 …
 }

Slide 30

Slide 30 text

EXTENDED PROPERTY KOTLIN fun FloatingActionButton.getBehaviour(): FloatingActionButton.Behavior? {
 … } val FloatingActionButton.behavior: FloatingActionButton.Behavior?
 get() {
 …
 } fab.behavior?.isAutoHideEnabled = true

Slide 31

Slide 31 text

MOAR LAMBDAS KOTLIN fun FloatingActionButton.hideCarefully(f: () -> Unit) {
 behavior?.isAutoHideEnabled = false
 hide(object : FloatingActionButton.OnVisibilityChangedListener() {
 override fun onHidden(fab: FloatingActionButton) {
 f()
 behavior?.isAutoHideEnabled = true
 }
 })
 } private fun FloatingActionButton.hideCarefully(f: () -> Unit) {
 behavior?.isAutoHideEnabled = false
 
 hide { visible ->
 if (!visible) {
 f()
 behavior?.isAutoHideEnabled = true
 }
 }
 }

Slide 32

Slide 32 text

MOAR LAMBDAS KOTLIN fun FloatingActionButton.hide(f: (visible: Boolean) -> Unit) {
 hide(object : FloatingActionButton.OnVisibilityChangedListener() {
 override fun onShown(fab: FloatingActionButton?) {
 f(true)
 }
 
 override fun onHidden(fab: FloatingActionButton?) {
 f(false)
 }
 })
 }

Slide 33

Slide 33 text

hideFab(fab, new Runnable() {
 @Override public void run() {
 …
 }
 });

Slide 34

Slide 34 text

hideFab(fab, new Runnable() {
 @Override public void run() {
 …
 }
 }); fab.hideCarefully {
 ...
 }

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

INLINE FUNCTIONS KOTLIN inline fun FloatingActionButton.hideCarefully(crossinline f: () -> Unit) {
 behavior?.isAutoHideEnabled = false
 
 hide { visible ->
 if (!visible) {
 f()
 behavior?.isAutoHideEnabled = true
 }
 }
 }

Slide 37

Slide 37 text

INLINE FUNCTIONS KOTLIN inline fun FloatingActionButton.hideCarefully(crossinline f: () -> Unit) {
 behavior?.isAutoHideEnabled = false
 
 hide { visible ->
 if (!visible) {
 f()
 behavior?.isAutoHideEnabled = true
 }
 }
 }

Slide 38

Slide 38 text

INLINE FUNCTIONS

Slide 39

Slide 39 text

INLINE FUNCTIONS fun supportsLollipop(f: () -> Unit) {
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
 f()
 }
 } supportsLollipop {
 window.statusBarColor = Color.BLACK
 }

Slide 40

Slide 40 text

INLINE FUNCTIONS fun supportsLollipop(f: () -> Unit) {
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
 f()
 }
 }

Slide 41

Slide 41 text

INLINE FUNCTIONS inline fun supportsLollipop(f: () -> Unit) {
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
 f()
 }
 }

Slide 42

Slide 42 text

ANKO ▸ Jetbrains Library ▸ Simplify Android Development ▸ DSL to write Android UI ▸ Asynchronous tasks ▸ SQLite made simple ▸ Alerts, dialogs ▸ … https://github.com/Kotlin/anko

Slide 43

Slide 43 text

ANKO verticalLayout {
 val name = editText()
 button("Say Hello") {
 onClick { toast("Hello, ${name.text}!") }
 }
 }

Slide 44

Slide 44 text

ANKO database.use {
 … }

Slide 45

Slide 45 text

ANKO database.use {
 … } alert { 
 title("Title")
 message("Message")
 okButton { toast("OK") }
 cancelButton { toast("Cancel") }
 customView { 
 editText { 
 hint = "Enter your name"
 }
 }
 }.show()

Slide 46

Slide 46 text

ANKO database.use {
 … } alert { 
 title("Title")
 message("Message")
 okButton { toast("OK") }
 cancelButton { toast("Cancel") }
 customView { 
 editText { 
 hint = "Enter your name"
 }
 }
 }.show() doAsync { 
 val text = myAsyncTask()
 uiThread { 
 textView.text = text
 }
 }

Slide 47

Slide 47 text

EXTENSION FUNCTIONS THAT RECEIVE EXTENSION FUNCTIONS

Slide 48

Slide 48 text

EXTENSION FUNCTIONS THAT RECEIVE EXTENSION FUNCTIONS inline fun Context.verticalLayout(f: LinearLayout.() -> Unit): LinearLayout {
 val linearLayout = LinearLayout(this)
 linearLayout.orientation = LinearLayout.VERTICAL
 linearLayout.f()
 return linearLayout
 } verticalLayout {
 setHorizontalGravity(...)
 addView(...)
 }

Slide 49

Slide 49 text

EXTENSION FUNCTIONS THAT RECEIVE EXTENSION FUNCTIONS inline fun Context.verticalLayout(f: LinearLayout.() -> Unit): LinearLayout {
 val linearLayout = LinearLayout(this)
 linearLayout.orientation = LinearLayout.VERTICAL
 linearLayout.f()
 return linearLayout
 } inline fun Context.verticalLayout2(f: LinearLayout.() -> Unit) = LinearLayout(this).apply {
 orientation = LinearLayout.VERTICAL
 f() 
 }

Slide 50

Slide 50 text

EXTENSION FUNCTIONS THAT RECEIVE EXTENSION FUNCTIONS inline fun Context.notify(id: Int, f: Notification.Builder.() -> Unit): Notification =
 with(Notification.Builder(this)) {
 f()
 val notification = build()
 notificationManager.notify(id, notification)
 notification
 }

Slide 51

Slide 51 text

EXTENSION FUNCTIONS THAT RECEIVE EXTENSION FUNCTIONS inline fun Context.notify(id: Int, f: Notification.Builder.() -> Unit): Notification =
 with(Notification.Builder(this)) {
 f()
 val notification = build()
 notificationManager.notify(id, notification)
 notification
 } val notification = notify(2) {
 title = "Notification title"
 setSmallIcon(R.drawable.not_icon)
 setLargeIcon(R.drawable.not_large_icon)
 }

Slide 52

Slide 52 text

KOTLIN ANDROID EXTENSIONS 
 
 
 
 
 


Slide 53

Slide 53 text

KOTLIN ANDROID EXTENSIONS

Slide 54

Slide 54 text

KOTLIN ANDROID EXTENSIONS override fun onCreate(savedInstanceState: Bundle?) {
 super.onCreate(savedInstanceState)
 setContentView(R.layout.activity_main)
 
 button.onClick { toast(editText.text.toString()) }
 }

Slide 55

Slide 55 text

KOTLIN 1.1 KOTLIN 1.1 BETA ▸ Co-routines ▸ Type aliases ▸ Inheritance in data classes ▸ … async {
 val repos = await { github.getRepos() }
 showList(repos)
 repos.forEach { repo ->
 val stats = await { github.getStats(repo.name) }
 showStats(repo, stats)
 }
 }