Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin for Android - The future is now

Kotlin for Android - The future is now

Kotlin is a reality for Android. Here, I show some examples of how Kotlin can help you improve your productivity on Android and make your life much easier.

Antonio Leiva

February 16, 2017
Tweet

More Decks by Antonio Leiva

Other Decks in Programming

Transcript

  1. 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;
 }
 }
  2. 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
  3. 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
  4. 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
  5. 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");
 }
  6. 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")
 }
  7. 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();
 }
 }
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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); …
 }
 }
  13. 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) { …
 
 }
 }
  14. CUSTOM VIEWS KOTLIN class KotlinView(context: Context, attrs: AttributeSet? = null,

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

    AttributeSet? = null, defStyleAttr: Int = 0
 ) : View(context, attrs, defStyleAttr)
  16. 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);
 }
 }
  17. 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);
 }
 });
 }
  18. 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() {
 …
 }
 });
  19. EXTENSIONS + LAMBDAS KOTLIN fab.getBehaviour()?.isAutoHideEnabled = false fun FloatingActionButton.getBehaviour(): FloatingActionButton.Behavior?

    {
 val lp = layoutParams as? CoordinatorLayout.LayoutParams
 return lp?.behavior as? FloatingActionButton.Behavior
 }
  20. 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 {
 ...
 }
  21. EXTENDED PROPERTY KOTLIN fun FloatingActionButton.getBehaviour(): FloatingActionButton.Behavior? {
 … } val

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

    FloatingActionButton.behavior: FloatingActionButton.Behavior?
 get() {
 …
 } fab.behavior?.isAutoHideEnabled = true
  23. 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
 }
 }
 }
  24. 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)
 }
 })
 }
  25. INLINE FUNCTIONS KOTLIN inline fun FloatingActionButton.hideCarefully(crossinline f: () -> Unit)

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

    {
 behavior?.isAutoHideEnabled = false
 
 hide { visible ->
 if (!visible) {
 f()
 behavior?.isAutoHideEnabled = true
 }
 }
 }
  27. INLINE FUNCTIONS fun supportsLollipop(f: () -> Unit) {
 if (Build.VERSION.SDK_INT

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

    (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
 f()
 }
 }
  29. ANKO ▸ Jetbrains Library ▸ Simplify Android Development ▸ DSL

    to write Android UI ▸ Asynchronous tasks ▸ SQLite made simple ▸ Alerts, dialogs ▸ … https://github.com/Kotlin/anko
  30. ANKO verticalLayout {
 val name = editText()
 button("Say Hello") {


    onClick { toast("Hello, ${name.text}!") }
 }
 }
  31. ANKO database.use {
 … } alert { 
 title("Title")
 message("Message")


    okButton { toast("OK") }
 cancelButton { toast("Cancel") }
 customView { 
 editText { 
 hint = "Enter your name"
 }
 }
 }.show()
  32. 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
 }
 }
  33. 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(...)
 }
  34. 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() 
 }
  35. 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
 }
  36. 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)
 }
  37. KOTLIN ANDROID EXTENSIONS <LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">
 
 <EditText


    android:id="@+id/editText"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"/>
 
 <Button
 android:id="@+id/button"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Click me"/>
 
 </LinearLayout>
  38. 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)
 }
 }