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

Android & Kotlin: The code awakens (episode 02)...

Android & Kotlin: The code awakens (episode 02) - 2/3

Kotlin vs Java - Part 2
Null-safety
Elvis Operator
Smart-cast
Collections

Avatar for Omar Miatello

Omar Miatello

December 17, 2015
Tweet

More Decks by Omar Miatello

Other Decks in Technology

Transcript

  1. Omar Miatello Member of GDG Milano (Italy) Android Developer @

    Satispay Personal profile google.com/+OmarMiatello Google+ Community: Kotlin for Android goo.gl/mUKF1w Google Presentation #01 goo.gl/0jHLmE #02 goo.gl/h3uG8M #03 goo.gl/hnwvqu Google Photo #01 goo.gl/photos/cKP9L6zqZcxDRGzQ8 #02 goo.gl/photos/sXdpkbihCi5xAAnx7 #03 goo.gl/photos/P6kGhLE8yrWYnhAW6
  2. Previously on Android & Kotlin #01: goo.gl/0jHLmE • Properties val

    a: Int = 1 // val = READ ONLY (getter) var b: Int = 1 // var = READ/WRITE (getter/setter) • String templates "My name is $name $surname" • Lambdas view.setOnClickListener { Log.d("TAG", "Item clicked!") } • Delegated properties (example: lazy) val item by lazy { MyItem() }
  3. dummy/HeroAdapter.java public class HeroAdapter extends RecyclerView.Adapter<HeroAdapter.ViewHolder> { private final List<HeroItem>

    mValues; private final HeroOnClickListener mListener; public HeroAdapter(List<HeroItem> items, HeroOnClickListener listener) { mValues = items; mListener = listener; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_hero, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(final ViewHolder holder, int position) { HeroItem item = mValues.get(position); “Convert Java File to Kotlin File” CTRL + ALT + SHIFT + K (or CMD + ALT + SHIFT + K)
  4. class MyKotlinClass { val a: String = "ciao" val b:

    String = null // Error at compile time } #5 Kotlin - Null Safety http://kotlinlang.org/docs/reference/null-safety.html vs
  5. class MyKotlinClass { val a: String = "ciao" val b:

    String = null // Error at compile time val c: String? = null val d: String? = "ok" } #5 Kotlin - Null Safety http://kotlinlang.org/docs/reference/null-safety.html vs
  6. class MyKotlinClass { val a: String = "ciao" val b:

    String = null // Error at compile time val c: String? = null val d: String? = "ok" fun example(e: String, f: String?) { e.length() f.length() // Error at compile time } } static class MyUtils { void example(String e, String f) { e.length(); // throw NullPointerException? f.length(); // throw NullPointerException? } } #5 Kotlin - Null Safety http://kotlinlang.org/docs/reference/null-safety.html vs
  7. class MyKotlinClass { val a: String = "ciao" val b:

    String = null // Error at compile time val c: String? = null val d: String? = "ok" fun example(e: String, f: String?) { e.length() f.length() // Error at compile time f?.length() } } static class MyUtils { void example(String e, String f) { e.length(); // throw NullPointerException? f.length(); // throw NullPointerException? } } #5 Kotlin - Null Safety http://kotlinlang.org/docs/reference/null-safety.html vs
  8. class MyKotlinClass { val a: String = "ciao" val b:

    String = null // Error at compile time val c: String? = null val d: String? = "ok" fun example(e: String, f: String?) { e.length() f.length() // Error at compile time f?.length() if (f != null) { f.length() } } } static class MyUtils { void example(String e, String f) { e.length(); // throw NullPointerException? f.length(); // throw NullPointerException? if (e != null) { e.length(); } if (f != null) { e.length(); } } } #5 Kotlin - Null Safety http://kotlinlang.org/docs/reference/null-safety.html vs
  9. val map = mapOf( "dog" to "woof", "cat" to "meow",

    "bird" to "tweet", "mouse" to "squeek") fun sound(animal: String): String? { return map.get(animal) } class MyUtils { static Map<String, String> map = // ... static String sound(String animal) { return map.get(animal); } } #6 Kotlin - Elvis Operator http://kotlinlang.org/docs/reference/idioms.html#if-not-null-and-else-shorthand vs
  10. val map = mapOf( "dog" to "woof", "cat" to "meow",

    "bird" to "tweet", "mouse" to "squeek") fun sound(animal: String): String? { return map.get(animal) } fun example() { val foxSay = sound("fox") ?: "No one knows" } class MyUtils { static Map<String, String> map = // ... static String sound(String animal) { return map.get(animal); } static void example() { String s = sound("fox"); String foxSay = s != null ? s : "No one knows"; } } #6 Kotlin - Elvis Operator http://kotlinlang.org/docs/reference/idioms.html#if-not-null-and-else-shorthand vs
  11. val map = mapOf( "dog" to "woof", "cat" to "meow",

    "bird" to "tweet", "mouse" to "squeek") fun sound(animal: String): String? { return map.get(animal) } fun example() { val foxSay = sound("fox") ?: "No one knows" } class MyUtils { static Map<String, String> map = // ... static String sound(String animal) { return map.get(animal); } static void example() { String s = sound("fox"); String foxSay = s != null ? s : "No one knows"; } } #6 Kotlin - Elvis Operator http://kotlinlang.org/docs/reference/idioms.html#if-not-null-and-else-shorthand vs
  12. class MyUtils { static void example(View myView) { if (myView

    instanceof ImageView) { } } } #7 Kotlin - Smart Cast http://kotlinlang.org/docs/reference/typecasts.html#smart-casts vs
  13. class MyUtils { static void example(View myView) { if (myView

    instanceof ImageView) { ImageView imageView = (ImageView) myView; } } } #7 Kotlin - Smart Cast http://kotlinlang.org/docs/reference/typecasts.html#smart-casts vs
  14. class MyUtils { static void example(View myView) { if (myView

    instanceof ImageView) { ImageView imageView = (ImageView) myView; imageView.setImageAlpha(10); } } } #7 Kotlin - Smart Cast http://kotlinlang.org/docs/reference/typecasts.html#smart-casts vs
  15. class MyUtils { static void example(View myView) { if (myView

    instanceof ImageView) { ImageView imageView = (ImageView) myView; imageView.setImageAlpha(10); } else if (myView instanceof TextView) { TextView textView = (TextView) myView; textView.setText("Ciao"); } } } #7 Kotlin - Smart Cast http://kotlinlang.org/docs/reference/typecasts.html#smart-casts vs
  16. fun example1(myView: View) { if (myView is ImageView) { myView.setImageAlpha(10)

    } else if (myView is TextView) { myView.setText("Ciao") } } class MyUtils { static void example(View myView) { if (myView instanceof ImageView) { ImageView imageView = (ImageView) myView; imageView.setImageAlpha(10); } else if (myView instanceof TextView) { TextView textView = (TextView) myView; textView.setText("Ciao"); } } } #7 Kotlin - Smart Cast http://kotlinlang.org/docs/reference/typecasts.html#smart-casts vs
  17. fun example1(myView: View) { if (myView is ImageView) { myView.setImageAlpha(10)

    } else if (myView is TextView) { myView.setText("Ciao") } } fun example2(myView: View) { when (myView) { is ImageView -> myView.imageAlpha = 10 is TextView -> myView.text = "Ciao" } } class MyUtils { static void example(View myView) { if (myView instanceof ImageView) { ImageView imageView = (ImageView) myView; imageView.setImageAlpha(10); } else if (myView instanceof TextView) { TextView textView = (TextView) myView; textView.setText("Ciao"); } } } #7 Kotlin - Smart Cast http://kotlinlang.org/docs/reference/typecasts.html#smart-casts vs
  18. fun example() { val os = listOf("Android", "iOS", null, "Windows

    Phone") } class MyUtils { static void example() { List<String> os = Arrays.asList("Android", "iOS", null, "Windows Phone"); } } #8 Kotlin - Using collections http://kotlinlang.org/docs/reference/basic-syntax.html#using-collections vs
  19. fun example() { val os = listOf("Android", "iOS", null, "Windows

    Phone") os.filterNotNull() } class MyUtils { static void example() { List<String> os = Arrays.asList("Android", "iOS", null, "Windows Phone"); List<String> osNotNull = new ArrayList<>(); for (String name : os) { if (name != null) osNotNull.add(name); } } } #8 Kotlin - Using collections http://kotlinlang.org/docs/reference/basic-syntax.html#using-collections vs
  20. fun example() { val os = listOf("Android", "iOS", null, "Windows

    Phone") os.filterNotNull().sortedBy { it.length() } } class MyUtils { static void example() { List<String> os = Arrays.asList("Android", "iOS", null, "Windows Phone"); List<String> osNotNull = new ArrayList<>(); for (String name : os) { if (name != null) osNotNull.add(name); } Collections.sort(osNotNull, new Comparator<String>() { @Override public int compare(String l, String r) { return r.length() - l.length(); } }); } } #8 Kotlin - Using collections http://kotlinlang.org/docs/reference/basic-syntax.html#using-collections vs
  21. fun example() { val os = listOf("Android", "iOS", null, "Windows

    Phone") os.filterNotNull().sortedBy { it.length() } .map { it.toUpperCase() } } class MyUtils { static void example() { List<String> os = Arrays.asList("Android", "iOS", null, "Windows Phone"); List<String> osNotNull = new ArrayList<>(); for (String name : os) { if (name != null) osNotNull.add(name); } Collections.sort(osNotNull, new Comparator<String>() { @Override public int compare(String l, String r) { return l.length() - r.length(); } }); for (String name : osNotNull) { String value = name.toUpperCase(); } } } #8 Kotlin - Using collections http://kotlinlang.org/docs/reference/basic-syntax.html#using-collections vs
  22. fun example() { val os = listOf("Android", "iOS", null, "Windows

    Phone") os.filterNotNull().sortedBy { it.length() } .map { it.toUpperCase() } .forEach { print(it) } } class MyUtils { static void example() { List<String> os = Arrays.asList("Android", "iOS", null, "Windows Phone"); List<String> osNotNull = new ArrayList<>(); for (String name : os) { if (name != null) osNotNull.add(name); } Collections.sort(osNotNull, new Comparator<String>() { @Override public int compare(String l, String r) { return l.length() - r.length(); } }); for (String name : osNotNull) { String value = name.toUpperCase(); print(value); } } } #8 Kotlin - Using collections http://kotlinlang.org/docs/reference/basic-syntax.html#using-collections vs
  23. dummy/HeroDummyContent.kt object HeroDummyContent { private val MALE = "Male" private

    val FEMALE = "Female" val ITEMS = listOf( HeroItem("Hulk", MALE, 9), HeroItem("Iron Man", MALE, 8), HeroItem("Thor", MALE, 8), HeroItem("Jessica Jones", FEMALE, 2), HeroItem("Spiderman", MALE, 4) ) }
  24. dummy/HeroDummyContent.kt > object vs class object HeroDummyContent { private val

    MALE = "Male" private val FEMALE = "Female" val ITEMS = listOf( HeroItem("Hulk", MALE, 9), HeroItem("Iron Man", MALE, 8), HeroItem("Thor", MALE, 8), HeroItem("Jessica Jones", FEMALE, 2), HeroItem("Spiderman", MALE, 4) ) }
  25. dummy/HeroDummyContent.kt > listOf(...) object HeroDummyContent { private val MALE =

    "Male" private val FEMALE = "Female" val ITEMS = listOf( HeroItem("Hulk", MALE, 9), HeroItem("Iron Man", MALE, 8), HeroItem("Thor", MALE, 8), HeroItem("Jessica Jones", FEMALE, 2), HeroItem("Spiderman", MALE, 4) ) }
  26. dummy/HeroAdapter.kt class HeroAdapter(val mValues: List<HeroItem>, val mListener: Function1<HeroItem, Unit>?) :

    RecyclerView.Adapter<HeroAdapter.ViewHolder>() { // ... override fun onBindViewHolder(holder: ViewHolder, position: Int) { val hero = mValues[position] holder.item = hero holder.nameView.text = "${hero.name} (Power: ${hero.power})" holder.genderView.text = hero.gender holder.itemView.setOnClickListener { mListener?.invoke(hero) } } // ... }
  27. dummy/HeroAdapter.kt > String template class HeroAdapter(val mValues: List<HeroItem>, val mListener:

    Function1<HeroItem, Unit>?) : RecyclerView.Adapter<HeroAdapter.ViewHolder>() { // ... override fun onBindViewHolder(holder: ViewHolder, position: Int) { val hero = mValues[position] holder.item = hero holder.nameView.text = "${hero.name} (Power: ${hero.power})" holder.genderView.text = hero.gender holder.itemView.setOnClickListener { mListener?.invoke(hero) } } // ... }
  28. MainActivity.kt class MainActivity : AppCompatActivity() { private var currentHero: HeroItem?

    = null private val adapter by lazy { HeroAdapter(HeroDummyContent.ITEMS) { // onItemClick ... } } // ... }
  29. MainActivity.kt > adapter (lazy) HeroAdapter(HeroDummyContent.ITEMS) { // onClick val previousHero

    = currentHero if (previousHero != null) { // fight val conclusion = if (previousHero.power == it.power) { "It's a draw" } else if (previousHero.power > it.power) { "${previousHero.name} wins!" } else { "${it.name} wins!" } Snackbar.make(fab, "${previousHero.name} vs ${it.name}!\n$conclusion", Snackbar.LENGTH_LONG).show() currentHero = null } else { // assign current hero Snackbar.make(fab, "Choose: ${it.name}", Snackbar.LENGTH_SHORT).show() currentHero = it } }
  30. MainActivity.kt > adapter (lazy) > Smart cast HeroAdapter(HeroDummyContent.ITEMS) { //

    onClick val previousHero = currentHero if (previousHero != null) { // fight val conclusion = if (previousHero.power == it.power) { "It's a draw" } else if (previousHero.power > it.power) { "${previousHero.name} wins!" } else { "${it.name} wins!" } Snackbar.make(fab, "${previousHero.name} vs ${it.name}!\n$conclusion", Snackbar.LENGTH_LONG).show() currentHero = null } else { // assign current hero Snackbar.make(fab, "Choose: ${it.name}", Snackbar.LENGTH_SHORT).show() currentHero = it } }
  31. MainActivity.kt > adapter (lazy) > return if expression HeroAdapter(HeroDummyContent.ITEMS) {

    // onClick val previousHero = currentHero if (previousHero != null) { // fight val conclusion = if (previousHero.power == it.power) { "It's a draw" } else if (previousHero.power > it.power) { "${previousHero.name} wins!" } else { "${it.name} wins!" } Snackbar.make(fab, "${previousHero.name} vs ${it.name}!\n$conclusion", Snackbar.LENGTH_LONG).show() currentHero = null } else { // assign current hero Snackbar.make(fab, "Choose: ${it.name}", Snackbar.LENGTH_SHORT).show() currentHero = it } }
  32. Questions? Developers playground - #EX2 - Aggiungere le proprietà a

    HeroItem: hair (String?), eyes (String?) - Mostrarle (se presenti) nella lista - Se vengono scelti 2 eroi di sesso opposto, viene creato un nuovo eroe - Si possono usare le proprietà dei genitori, oppure dei valori di default se mancano Start with: https://github.com/jacklt/KotlinExample/tree/ex1 Solution: https://github.com/jacklt/KotlinExample/tree/ex2