KrakDroid: Scala on Android

3,558 views

Published on

A revamped talk about #scala programming on #android. Presentation given at krakdroid 2012. http://krakdroid.pl

Published in: Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,558
On SlideShare
0
From Embeds
0
Number of Embeds
119
Actions
Shares
0
Downloads
52
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

KrakDroid: Scala on Android

  1. 1. Scala Android Konrad Malawski / @ktosopl GDG / PJUG / KSUG / SCKRK KrakDroid 14.12.2012Sunday, December 16, 12
  2. 2. Sunday, December 16, 12
  3. 3. Sunday, December 16, 12
  4. 4. Scala isSunday, December 16, 12
  5. 5. Scala isSunday, December 16, 12
  6. 6. Scala isSunday, December 16, 12
  7. 7. Scala isSunday, December 16, 12
  8. 8. Scala is SimpleSunday, December 16, 12
  9. 9. Scala is Simple , but Hard.Sunday, December 16, 12
  10. 10. Scala is Simple.Sunday, December 16, 12
  11. 11. Scala is Simple.Sunday, December 16, 12
  12. 12. Scala is Hard. http://apocalisp.wordpress.com/2010/10/26/ type-level-programming -in-scala-part-7-natural-transformation%C2%A0literals/Sunday, December 16, 12
  13. 13. Scala is Hard.object  Param  {    implicit  def  pToT[A[_],  B[_]](f:  (p:  Param[A])  =>  B[p.T]):  A~>B  =  new  (A  ~>  B)  {        def  apply[s](a:  A[s]):  B[s]  =  {            val  v:  Param[A]  {  type  T  =  s}  =  new  Param[A]  {                  type  T  =  s                def  in  =  a            }            f(v)        }    }} http://apocalisp.wordpress.com/2010/10/26/ type-level-programming -in-scala-part-7-natural-transformation%C2%A0literals/Sunday, December 16, 12
  14. 14. Scala isSunday, December 16, 12
  15. 15. Scala is A Functional,Sunday, December 16, 12
  16. 16. Scala is A Functional, Object Oriented,Sunday, December 16, 12
  17. 17. Scala is A Functional, Object Oriented, Statically Typed,Sunday, December 16, 12
  18. 18. Scala is A Functional, Object Oriented, Statically Typed, Scalable,Sunday, December 16, 12
  19. 19. Scala is A Functional, Object Oriented, Statically Typed, Scalable, Language...Sunday, December 16, 12
  20. 20. Scala is A Functional, Object Oriented, Statically Typed, Scalable, Language... ...running on the JVM and DVM!Sunday, December 16, 12
  21. 21. AndroidSunday, December 16, 12
  22. 22. findViewById public class MyActivity extends Activity { ListView comments; Button newComment; @Override void onCreate(Bundle bundle) { super.onCreate(bundle); comments = (ListView) findViewById(R.id.comments); newComment = (Button) findViewById(R.id.new_comment); // ... } }Sunday, December 16, 12
  23. 23. findViewById public class MyActivity extends Activity { ListView comments; is null at first... Button newComment; @Override void onCreate(Bundle bundle) { super.onCreate(bundle); comments = (ListView) findViewById(R.id.comments); newComment = (Button) findViewById(R.id.new_comment); // ... } }Sunday, December 16, 12
  24. 24. findViewById public class MyActivity extends Activity { ListView comments; Button newComment; initialized in @Override method... void onCreate(Bundle bundle) { super.onCreate(bundle); comments = (ListView) findViewById(R.id.comments); newComment = (Button) findViewById(R.id.new_comment); // ... } }Sunday, December 16, 12
  25. 25. findViewById public class MyActivity extends Activity { ListView comments; Button newComment; @Override void onCreate(Bundle bundle) { super.onCreate(bundle); comments = (ListView) findViewById(R.id.comments); newComment = (Button) findViewById(R.id.new_comment); // ... } } Explicit casting!Sunday, December 16, 12
  26. 26. Robo Guice So many public class MakeANoteActivity extends Activity words... implements View.OnClickListener { public static final String PHOTO_PATH = "picture_path"; public static final String PHOTO_ATTACHED = "photo_attached"; @Inject SessionManager sessionManager; @Inject LocationHelper locationHelper; @Inject PhotoHelper photoHelper; @Inject Application context; @Inject CalibrationHelper calibrationHelper; @InjectView(R.id.attach_photo) Button attachPhoto; @InjectView(R.id.note_text) EditText noteText; @InjectView(R.id.save_button) Button save; @InjectView(R.id.date) TextView dateText; @InjectView(R.id.share) Button share; @InjectResource(R.string.im_aircasting) String imAircasting; @InjectResource(R.string.share_with) String shareWith; // ... }Sunday, December 16, 12
  27. 27. Robo Guice public class MakeANoteActivity extends RoboActivity implements View.OnClickListener { public static final String PHOTO_PATH = "picture_path"; public static final String PHOTO_ATTACHED = "photo_attached"; @Inject SessionManager sessionManager; @Inject LocationHelper locationHelper; Type changes in XML, @Inject PhotoHelper photoHelper; but not here... @Inject Application context; ClassCastException! @Inject CalibrationHelper calibrationHelper; @InjectView(R.id.attach_photo) Button attachPhoto; @InjectView(R.id.note_text) EditText noteText; @InjectView(R.id.save_button) Button save; @InjectView(R.id.date) TextView dateText; @InjectView(R.id.share) Button share; @InjectResource(R.string.im_aircasting) String imAircasting; @InjectResource(R.string.share_with) String shareWith; // ... }Sunday, December 16, 12
  28. 28. Robo Guice public class MakeANoteActivity extends RoboActivity implements View.OnClickListener { public static final String PHOTO_PATH = "picture_path"; public static final String PHOTO_ATTACHED = "photo_attached"; @Inject SessionManager sessionManager; @Inject LocationHelper locationHelper; Guice is eager. @Inject PhotoHelper photoHelper; Startup can take a few seconds! @Inject Application context; @Inject CalibrationHelper calibrationHelper; @InjectView(R.id.attach_photo) Button attachPhoto; @InjectView(R.id.note_text) EditText noteText; @InjectView(R.id.save_button) Button save; @InjectView(R.id.date) TextView dateText; @InjectView(R.id.share) Button share; @InjectResource(R.string.im_aircasting) String imAircasting; @InjectResource(R.string.share_with) String shareWith; // ... }Sunday, December 16, 12
  29. 29. Stairway to ScalaSunday, December 16, 12
  30. 30. Another look at the Java code public class MakeANoteActivity extends RoboActivity implements View.OnClickListener { public static final String PHOTO_PATH = "picture_path"; public static final String PHOTO_ATTACHED = "photo_attached"; @Inject SessionManager sessionManager; @Inject LocationHelper locationHelper; @Inject PhotoHelper photoHelper; @Inject Application context; @Inject CalibrationHelper calibrationHelper; @InjectView(R.id.attach_photo) Button attachPhoto; @InjectView(R.id.note_text) EditText noteText; @InjectView(R.id.save_button) Button save; @InjectView(R.id.date) TextView dateText; @InjectView(R.id.share) Button share; @InjectResource(R.string.im_aircasting) String imAircasting; @InjectResource(R.string.share_with) String shareWith; // ... }Sunday, December 16, 12
  31. 31. What if... Scala? public class MakeANoteActivity extends RoboActivity implements View.OnClickListener { public static final String PHOTO_PATH = "picture_path"; public static final String PHOTO_ATTACHED = "photo_attached"; @Inject SessionManager sessionManager; @Inject LocationHelper locationHelper; @Inject PhotoHelper photoHelper; @Inject Application context; @Inject CalibrationHelper calibrationHelper; @InjectView(R.id.attach_photo) Button attachPhoto; @InjectView(R.id.note_text) EditText noteText; @InjectView(R.id.save_button) Button save; @InjectView(R.id.date) TextView dateText; @InjectView(R.id.share) Button share; @InjectResource(R.string.im_aircasting) String imAircasting; @InjectResource(R.string.share_with) String shareWith; // ... }Sunday, December 16, 12
  32. 32. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val imAircasting = findResource[String](R.string.im_aircasting) val shareWith = findResource[String](R.string.share_with) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  33. 33. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { public is default. = "picture_path" val PhotoPath val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  34. 34. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" ScalaActivity gives us some val PhotoAttached = "photo_attached" magic methods lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  35. 35. What if... Scala? class MakeANoteActivity extends ScalaActivity It’s so easy, with View.OnClickListener YOU can implement it! with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" ScalaActivity gives us some val PhotoAttached = "photo_attached" magic methods lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  36. 36. What if... Scala? class MakeANoteActivity extends ScalaActivity It’s so easy, with View.OnClickListener YOU can implement it! with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" ScalaActivity gives us some val PhotoAttached = "photo_attached" magic methods lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  37. 37. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations Instead of “...Helper”, { use Traits. val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  38. 38. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" Type Inference lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  39. 39. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get Who’s missing here? lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  40. 40. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get lazy initialization lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  41. 41. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get Needs Context lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  42. 42. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get What’s the type here?!? lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  43. 43. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get What’s the type here?!? Typed Resource - “a better R” lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  44. 44. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get What’s the type here?!? Typed Resource - “a better R” lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) XML Type changes... Type here changes! val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  45. 45. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get What’s the type here?!? Typed Resource - “a better R” lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share: Button = findView(TR.share) You can be explicit though! val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  46. 46. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = Like @InjectResource, but findView(TR.share) smarter val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() } Manifests vs. Type ErasureSunday, December 16, 12
  47. 47. What if... Scala? class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) Does String have a toast() val username = findResource[String](R.string.my_username) method? val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() } Implicit ConversionSunday, December 16, 12
  48. 48. Typed ResourceSunday, December 16, 12
  49. 49. Typed Resource = Better RSunday, December 16, 12
  50. 50. Typed Resource = Better RSunday, December 16, 12
  51. 51. Typed Resource = Better R class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  52. 52. Typed Resource = Better R class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) Typed Resource val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() }Sunday, December 16, 12
  53. 53. Typed Resource = Better R case class TypedResource[T](id: Int) case class TypedLayout(id: Int) object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager) val workspaces = TypedResource[ExpandableListView](R.id.workspaces) val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ... }Sunday, December 16, 12
  54. 54. Typed Resource = Better R case class TypedResource[T](id: Int) case class TypedLayout(id: Int) object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager) val workspaces = TypedResource[ExpandableListView](R.id.workspaces) val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ... }Sunday, December 16, 12
  55. 55. Typed Resource = Better R case class TypedResource[T](id: Int) case class TypedLayout(id: Int) Wrappers object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager) val workspaces = TypedResource[ExpandableListView](R.id.workspaces) val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ... }Sunday, December 16, 12
  56. 56. Typed Resource = Better R case class TypedResource[T](id: Int) case class TypedLayout(id: Int) object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager) val workspaces = TypedResource[ExpandableListView](R.id.workspaces) val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ... }Sunday, December 16, 12
  57. 57. Typed Resource = Better R case class TypedResource[T](id: Int) case class TypedLayout(id: Int) object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager) val workspaces = TypedResource[ExpandableListView](R.id.workspaces) val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ... }Sunday, December 16, 12
  58. 58. TR in Action class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath = "picture_path" val PhotoAttached = "photo_attached" lazy val sessionManager = SessionManager.get // magic here but lazy val locationManager = LocationManager.get // we’ll see this later! lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share) // magic here too, but we’ll implement this in a few slides! val imAircasting = findResource[String](R.string.im_aircasting) val shareWith = findResource[String](R.string.share_with) // ... }Sunday, December 16, 12
  59. 59. TypesSunday, December 16, 12
  60. 60. Types You always have the type information at hand.Sunday, December 16, 12
  61. 61. Types You always have the type information at hand. (IntelliJ IDEA, Ensmine/Emacs, Eclipse) ⌘ SHIFT I ALT =Sunday, December 16, 12
  62. 62. An Implicit ContextSunday, December 16, 12
  63. 63. An Implicit Context Implicit != ExplicitSunday, December 16, 12
  64. 64. An Implicit Context Implicit != Explicit def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() } toastMyName(”Siegfried”, getContext)Sunday, December 16, 12
  65. 65. An Implicit Context Implicit != Explicit def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() } Explicit Parameter toastMyName(”Siegfried”, getContext)Sunday, December 16, 12
  66. 66. An Implicit Context Implicit != Explicit def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() } Explicit Parameter toastMyName(”Siegfried”, getContext)Sunday, December 16, 12
  67. 67. An Implicit Context Implicit != Explicit Import inside a method! def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() } toastMyName(”Siegfried”, getContext)Sunday, December 16, 12
  68. 68. An Implicit Context Implicit != Explicit def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() } toastMyName(”Siegfried”, getContext)Sunday, December 16, 12
  69. 69. An Implicit Context Implicit != Explicit def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() }Sunday, December 16, 12
  70. 70. Implicit Parameters Implicit != Explicit def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() Implicit Parameter }Sunday, December 16, 12
  71. 71. Implicit Parameters Implicit != Explicit def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() }Sunday, December 16, 12
  72. 72. Implicit Parameters Implicit != Explicit def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() } toastMyName("Siegfried")Sunday, December 16, 12
  73. 73. Implicit Parameters Implicit != Explicit def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() } implicit val context: Context = getContext toastMyName("Siegfried")Sunday, December 16, 12
  74. 74. Implicit Parameters Implicit != Explicit def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() } implicit val context: Context = getContext toastMyName("Siegfried") toastMyName("Siegfried")(context)Sunday, December 16, 12
  75. 75. An Implicit Context class ScalaActivity extends Activity with ImplicitContextSunday, December 16, 12
  76. 76. An Implicit Context class ScalaActivity extends Activity with ImplicitContext trait ImplicitContext { this: Activity => implicit val ctx = getContext }Sunday, December 16, 12
  77. 77. An Implicit Context class ScalaActivity extends Activity with ImplicitContext “I can be only mixed into an Activity.” trait ImplicitContext { this: Activity => implicit val ctx = getContext }Sunday, December 16, 12
  78. 78. An Implicit Context class ScalaActivity extends Activity with ImplicitContext “I can be only mixed into an Activity.” trait ImplicitContext { this: Activity => implicit val ctx = getContext } So I know this method!Sunday, December 16, 12
  79. 79. Manifests vs. Type ErasureSunday, December 16, 12
  80. 80. Manifests vs. Type ErasureSunday, December 16, 12
  81. 81. Manifests vs. Type Erasure List<Thing> t = marshaller.parseList("[]") JavaSunday, December 16, 12
  82. 82. Manifests vs. Type Erasure Uhm... List<Object>...? List<Thing> t = marshaller.parseList("[]") JavaSunday, December 16, 12
  83. 83. Manifests vs. Type Erasure Uhm... List<Object>...? List<Thing> t = marshaller.parseList("[]") Java List<Thing> t = marshaller.parseList("[]", Thing.class)Sunday, December 16, 12
  84. 84. Manifests vs. Type Erasure Uhm... List<Object>...? List<Thing> t = marshaller.parseList("[]") Java Oh! List<Thing>, sure! List<Thing> t = marshaller.parseList("[]", Thing.class)Sunday, December 16, 12
  85. 85. Manifests vs. Type Erasure Uhm... List<Object>...? List<Thing> t = marshaller.parseList("[]") Java Oh! List<Thing>, sure! List<Thing> t = marshaller.parseList("[]", Thing.class) Scala val t: List[Thing] = marshaller.parseList("[]")Sunday, December 16, 12
  86. 86. Manifests vs. Type Erasure Uhm... List<Object>...? List<Thing> t = marshaller.parseList("[]") Java Oh! List<Thing>, sure! List<Thing> t = marshaller.parseList("[]", Thing.class) Scala val t: List[Thing] = marshaller.parseList("[]") List[Thing]!Sunday, December 16, 12
  87. 87. Manifests vs. Type Erasure val shareWith = findResource[String](R.string.share_with)Sunday, December 16, 12
  88. 88. Manifests vs. Type Erasure val shareWith = findResource[String](R.string.share_with)Sunday, December 16, 12
  89. 89. Manifests vs. Type Erasure def findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] case other => throw new UnableToResolveResource(ofType = other, id = id) } val shareWith = findResource[String](R.string.share_with)Sunday, December 16, 12
  90. 90. Manifests vs. Type Erasure def findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] implicit case other => throw new UnableToResolveResource(ofType = other, id = id) } val shareWith = findResource[String](R.string.share_with)Sunday, December 16, 12
  91. 91. Manifests vs. Type Erasure def findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] implicit Manifest case other => throw new UnableToResolveResource(ofType = other, id = id) } val shareWith = findResource[String](R.string.share_with)Sunday, December 16, 12
  92. 92. Manifests vs. Type Erasure def findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] the type signature case other => throw new UnableToResolveResource(ofType = other, id = id) } val shareWith = findResource[String](R.string.share_with)Sunday, December 16, 12
  93. 93. Manifests vs. Type Erasure def findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] see the type... at runtime case "java.util.ArrayList[java.lang.String]" => newArrayList(ctx.getString(id).asInstanceOf[T]) case other => throw new UnableToResolveResource(ofType = other, id = id) } val shareWith = findResource[String](R.string.share_with)Sunday, December 16, 12
  94. 94. Manifests vs. Type Erasure def findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] case "java.util.ArrayList[java.lang.String]" => newArrayList(ctx.getString(id).asInstanceOf[T]) case "Int" => ctx.getString(id).toInt.asInstanceOf[T] case other => throw new UnableToResolveResource(ofType = other, id = id) } val shareWith = findResource[String](R.string.share_with)Sunday, December 16, 12
  95. 95. Manifests vs. Type Erasure def findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] case "java.util.ArrayList[java.lang.String]" => newArrayList(ctx.getString(id).asInstanceOf[T]) case "Int" => ctx.getString(id).toInt.asInstanceOf[T] case other => java.lang.String has this...? throw new UnableToResolveResource(ofType = other, id = id) } val shareWith = findResource[String](R.string.share_with)Sunday, December 16, 12
  96. 96. Implicit ConversionsSunday, December 16, 12
  97. 97. Implicit Conversions Implicit != ExplicitSunday, December 16, 12
  98. 98. Implicit Conversions Implicit != ExplicitSunday, December 16, 12
  99. 99. Implicit Conversions Implicit != ExplicitSunday, December 16, 12
  100. 100. Implicit Conversions Implicit != Explicit toastMyName("Siegfried")Sunday, December 16, 12
  101. 101. Implicit Conversions Implicit != Explicit Implicit Context, remember? toastMyName("Siegfried")Sunday, December 16, 12
  102. 102. Implicit Conversions Implicit != Explicit toastMyName("Siegfried") What if we could...Sunday, December 16, 12
  103. 103. Implicit Conversions Implicit != Explicit toastMyName("Siegfried") What if we could... "Siegfried".toast()Sunday, December 16, 12
  104. 104. Implicit Conversions Implicit != ExplicitSunday, December 16, 12
  105. 105. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? }Sunday, December 16, 12
  106. 106. Implicit Conversions Implicit != Explicit Decorator class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? }Sunday, December 16, 12
  107. 107. Implicit Conversions Implicit != Explicit Decorator Constructor class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? }Sunday, December 16, 12
  108. 108. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } new Toastable("Hello!").toast()Sunday, December 16, 12
  109. 109. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? }Sunday, December 16, 12
  110. 110. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } trait ScalaToasts { implicit def asToastable(str: String) = new Toastable(str) }Sunday, December 16, 12
  111. 111. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } Implicit Conversion: String => Toastable trait ScalaToasts { implicit def asToastable(str: String) = new Toastable(str) }Sunday, December 16, 12
  112. 112. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } Implicit Conversion: String => Toastable trait ScalaToasts { implicit def asToastable(str: String) = new Toastable(str) } asToastable("Hello!").toast()Sunday, December 16, 12
  113. 113. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } Implicit Conversion: String => Toastable trait ScalaToasts { implicit def asToastable(str: String) = new Toastable(str) }Sunday, December 16, 12
  114. 114. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } trait ScalaToasts { implicit def asToastable(str: String) = new Toastable(str) } class ExampleActivity extends Activity with ImplicitContext with ScalaToastsSunday, December 16, 12
  115. 115. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } trait ScalaToasts { implicit def asToastable(str: String) = new Toastable(str) } class ExampleActivity extends Activity with ImplicitContext with ScalaToastsSunday, December 16, 12
  116. 116. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } trait ScalaToasts { implicit def asToastable(str: String) = new Toastable(str) } "Hello!".toast() class ExampleActivity extends Activity with ImplicitContext with ScalaToastsSunday, December 16, 12
  117. 117. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } trait ScalaToasts { implicit def asToastable(str: String) = new Toastable(str) } "Hello!".toast() class ExampleActivity extends Activity with ImplicitContext with ScalaToastsSunday, December 16, 12
  118. 118. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } trait ScalaToasts { implicit def asToastable(str: String) = new Toastable(str) } "Hello!".toast() class ExampleActivity extends Activity with ImplicitContext with ScalaToastsSunday, December 16, 12
  119. 119. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } trait ScalaToasts { implicit def asToastable(str: String) = new Toastable(str) } "Hello!".toast() class ExampleActivity extends Activity with ImplicitContext with ScalaToastsSunday, December 16, 12
  120. 120. Implicit Conversions Implicit != Explicit class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } trait ScalaToasts { implicit def asToastable(str: String) = new Toastable(str) } "Hello!".toast() class ExampleActivity extends Activity asToastable("Hello!").toast() with ImplicitContext with ScalaToastsSunday, December 16, 12
  121. 121. Implicit ConversionsSunday, December 16, 12
  122. 122. CollectionsSunday, December 16, 12
  123. 123. POJOSunday, December 16, 12
  124. 124. public class Person { private final String name; private final String nick; POJO public Person(String name, String nick) { this.name = name; this.nick = nick; } public String getName() { return name; } public String getNick() { return nick; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Person)) return false; Person person = (Person) o; if (name != null ? !name.equals(person.name) : person.name != null) return false; if (nick != null ? !nick.equals(person.nick) : person.nick != null) return false; return true; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (surname != null ? surname.hashCode() : 0); return result; } }Sunday, December 16, 12
  125. 125. public class Person { private final String name; private final String nick; POJO public Person(String name, String nick) { this.name = name; this.nick = nick; } public String getName() { return name; } public String getNick() { return nick; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Person)) return false; Person person = (Person) o; if (name != null ? !name.equals(person.name) : person.name != null) return false; if (nick != null ? !nick.equals(person.nick) : person.nick != null) return false; return true; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (surname != null ? surname.hashCode() : 0); return result; } }Sunday, December 16, 12
  126. 126. POSO* *Actually just a Case Class case class Person(name: String, nick: String)Sunday, December 16, 12
  127. 127. POSO* *Actually just a Case Class val name: String case class Person(name: String, nick: String)Sunday, December 16, 12
  128. 128. Case Classes case class Person(name: String, nick: String)Sunday, December 16, 12
  129. 129. Case Classes case class Person(name: String, nick: String)Sunday, December 16, 12
  130. 130. Case Classes case class Person(name: String, nick: String) val person = Person("Bruce Wayne", "Manbat") // whoops!Sunday, December 16, 12
  131. 131. Case Classes case class Person(name: String, nick: String) val person = Person("Bruce Wayne", "Manbat") // whoops! val fixed = person.copy(nick = "Batman")Sunday, December 16, 12
  132. 132. Case Classes case class Person(name: String, nick: String) val person = Person("Bruce Wayne", "Manbat") // whoops! val fixed = person.copy(nick = "Batman") val self = Person(nick = "Ktoso" , name = "Konrad")Sunday, December 16, 12
  133. 133. Case Classes case class Person(name: String, nick: String) val person = Person("Bruce Wayne", "Manbat") // whoops! val fixed = person.copy(nick = "Batman") val self = Person(nick = "Ktoso" , name = "Konrad") val Person(name, hero) = person val hello = ”Hello” + name + ” ” + surnameSunday, December 16, 12
  134. 134. Case Classes case class Person(name: String, nick: String) val person = Person("Bruce Wayne", "Manbat") // whoops! val fixed = person.copy(nick = "Batman") val self = Person(nick = "Ktoso" , name = "Konrad") val Person(name, hero) = person val hello = ”Hello” + name + ” ” + surname fixed.toString should equal (”Person(Bruce Wayne, Batman)”) Still thinking assertThat().isEqualTo() is clean?Sunday, December 16, 12
  135. 135. Given a list of People, return all the Hero names.Sunday, December 16, 12
  136. 136. Given a list of People, return all the Hero names. public List<String> heroNames(List<Person> allPersons) { List<String> donePersons = new ArrayList<String>(allPersons.size()); for (Person person : allPersons) { if (person.isHero()) { donePersons.add(person.getName()); } } return ImmutableList.copyOf(donePersons); }Sunday, December 16, 12
  137. 137. Java with Guava at their Best Given a list of People, return all the Hero names.Sunday, December 16, 12
  138. 138. Java with Guava at their Best Given a list of People, return all the Hero names. return FluentIterable .from(people) .filter(new Predicate<Person>() { @Override public boolean apply(Person person) { return person != null && person.isHero(); } }) .transform(new Function<Person, String>() { @Override public String apply(Person input) { return input.getName(); } }) .toImmutableList();Sunday, December 16, 12
  139. 139. Sunday, December 16, 12
  140. 140. Java + Guava at their best Given a list of People, return all the Hero names.Sunday, December 16, 12
  141. 141. Java + Guava at their best Given a list of People, return all the Hero names. return FluentIterable .from(people) .filter(isSuperHero) .transform(heroToName) .toImmutableList(); Java, yet pretty slick :-) I <3 Guava.Sunday, December 16, 12
  142. 142. Scala Collections at Work Given a list of People, return all the Hero names.Sunday, December 16, 12
  143. 143. Scala Collections at Work Given a list of People, return all the Hero names. def heroNames(people: List[Person]) = people filter(_.isHero) map { _.name}Sunday, December 16, 12
  144. 144. And there’s more!Sunday, December 16, 12
  145. 145. Simple ThreadingSunday, December 16, 12
  146. 146. Simple Threading implicit val handler = new HandlerSunday, December 16, 12
  147. 147. Simple Threading implicit val handler = new Handler inUiThread { // ... }Sunday, December 16, 12
  148. 148. Simple Threading implicit val handler = new Handler inUiThread { // ... } inFutureWithProgressDialog(timeout = 10.seconds) { // ... }Sunday, December 16, 12
  149. 149. Simple Threading implicit val handler = new Handler inUiThread { // ... } inFutureWithProgressDialog(timeout = 10.seconds) { // ... } Implicit Conversion on IntSunday, December 16, 12
  150. 150. on___ button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Java // ... } });Sunday, December 16, 12
  151. 151. on___ button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Java // ... } }); button onClick { view => Scala // ... }Sunday, December 16, 12
  152. 152. SharedPreferencesSunday, December 16, 12
  153. 153. SharedPreferences KanbaneryPreferences.projectId = projectIdSunday, December 16, 12
  154. 154. SharedPreferences KanbaneryPreferences.projectId = projectId val name: Option[Long] = KanbaneryPreferences.projectIdSunday, December 16, 12
  155. 155. SharedPreferences KanbaneryPreferences.projectId = projectId val name: Option[Long] = KanbaneryPreferences.projectId What? No implicits?! Assume it works! Skip!Sunday, December 16, 12
  156. 156. SharedPreferences object KanbaneryPreferences { private val KeyLogin = "login" private def sharedPreferences(implicit ctx: Context) = ??? def login(implicit ctx: Context) = sharedPreferences.getString(KeyLogin, "")Sunday, December 16, 12
  157. 157. SharedPreferences object KanbaneryPreferences { private val KeyLogin = "login" private def sharedPreferences(implicit ctx: Context) = ??? def login(implicit ctx: Context) = sharedPreferences.getString(KeyLogin, "")Sunday, December 16, 12
  158. 158. SharedPreferences object KanbaneryPreferences { private val KeyLogin = "login" private def sharedPreferences(implicit ctx: Context) = ??? def login_=(number: String)(implicit ctx: Context) { withSharedPreferencesEditor { _.putString(KeyLogin, number) } }Sunday, December 16, 12
  159. 159. SharedPreferences object KanbaneryPreferences { private val KeyLogin = "login" private def sharedPreferences(implicit ctx: Context) = ??? def login_=(number: String)(implicit ctx: Context) { withSharedPreferencesEditor { _.putString(KeyLogin, number) } }Sunday, December 16, 12
  160. 160. SharedPreferences def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) { val editor = sharedPreferences.edit() block(editor) editor.commit() }Sunday, December 16, 12
  161. 161. SharedPreferences def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) { val editor = sharedPreferences.edit() block(editor) editor.commit() }Sunday, December 16, 12
  162. 162. SharedPreferences def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) { val editor = sharedPreferences.edit() block(editor) editor.commit() }Sunday, December 16, 12
  163. 163. SharedPreferences def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) { val editor = sharedPreferences.edit() block(editor) editor.commit() } withSharedPreferencesEditor { _.putString(KeyLogin, number) }Sunday, December 16, 12
  164. 164. String interpolation (scala 2.10)Sunday, December 16, 12
  165. 165. String interpolation (scala 2.10)Sunday, December 16, 12
  166. 166. String interpolation (scala 2.10)Sunday, December 16, 12
  167. 167. String interpolation (scala 2.10) Won’t compile!Sunday, December 16, 12
  168. 168. Let me warn you...Sunday, December 16, 12
  169. 169. Let me warn you... Scala is addictive.Sunday, December 16, 12
  170. 170. Let me warn you... Scala is addictive.Sunday, December 16, 12
  171. 171. Scala is addictive.Sunday, December 16, 12
  172. 172. Scala is addictive.Sunday, December 16, 12
  173. 173. Scala is addictive.Sunday, December 16, 12
  174. 174. Scala is addictive.Sunday, December 16, 12
  175. 175. def links = • Scala Lang http://www.scala-lang.org/ • Scala Koans http://www.scalakoans.org • Blog.Project13.pl - http://www.blog.project13.pl • SBT Android Plugin - https://github.com/jberkel/android-plugin • Kanbanery for Android - https://github.com/ktoso/kanbanery-tv • Check pl.project13.scala.android.* • Now OpenSource, in Scala, and Lunar Logic is helping to dev :-) • New version soon! Pull and play with it! • Scaloid https://github.com/pocorall/scaloid • Though I don’t think their impl. is very clean some things are v. nice!Sunday, December 16, 12
  176. 176. def links = • Scala Lang http://www.scala-lang.org/ • Scala Koans http://www.scalakoans.org • Blog.Project13.pl - http://www.blog.project13.pl • SBT Android Plugin - https://github.com/jberkel/android-plugin • Kanbanery for Android - https://github.com/ktoso/kanbanery-tv • Check pl.project13.scala.android.* • Now OpenSource, in Scala, and Lunar Logic is helping to dev :-) • New version soon! Pull and play with it! • Scaloid https://github.com/pocorall/scaloid • Though I don’t think their impl. is very clean some things are v. nice! Mailing lists rock!Sunday, December 16, 12
  177. 177. Konrad Malawski / @ktosopl GDG / PJUG / KSUG / SCKRK KrakDroid 14.12.2012Sunday, December 16, 12
  178. 178. I love feedback! <3 Konrad Malawski / @ktosopl GDG / PJUG / KSUG / SCKRK KrakDroid 14.12.2012Sunday, December 16, 12

×