SlideShare a Scribd company logo
Scala     Android



                                         Konrad Malawski / @ktosopl
                                    GeeCON / GDG / PJUG / KSUG / SCKRK
                                            JFokus 06.02.2013
Wednesday, February 6, 13
Konrad Malawski
                               twitter: ktosopl




Wednesday, February 6, 13
This will be...




Wednesday, February 6, 13
This will Not be...




Wednesday, February 6, 13
This will Not be...




Wednesday, February 6, 13
This will Not be...


                               a Java rant,
                             about app design.



Wednesday, February 6, 13
This will be about...




Wednesday, February 6, 13
This will be about...




Wednesday, February 6, 13
This will be about...


            shifting cognitive load
                writing less code
            fokus on goals, not means

Wednesday, February 6, 13
Scala is




Wednesday, February 6, 13
Scala is




Wednesday, February 6, 13
Scala is

                             Simple ,
                            but Hard.



Wednesday, February 6, 13
Scala is Simple.




Wednesday, February 6, 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/
Wednesday, February 6, 13
Scala is
                                   A Functional,
                                 Object Oriented,
                                 Statically Typed,
                                     Scalable,
                                    Language...

                            ...running on the JVM and DVM!




Wednesday, February 6, 13
Android




Wednesday, February 6, 13
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);
                     // ...
                   }
               }




Wednesday, February 6, 13
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);
                     // ...
                   }
               }




Wednesday, February 6, 13
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);
                     // ...
                   }
               }




Wednesday, February 6, 13
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!




Wednesday, February 6, 13
Robo Guice
                                           So many
                public class MakeANoteActivity
                   extends RoboActivity
                                           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;

                       // ...
                }




Wednesday, February 6, 13
Robo Guice
                public class MakeANoteActivity
                   extends RoboActivity
                   implements View.OnClickListener
                {
                                                                 Guice is eager.
                    public static final String PHOTO_PATH Startup can take a few seconds!
                                                           = "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;

                       // ...
                }




Wednesday, February 6, 13
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;

                       // ...
                }




Wednesday, February 6, 13
Stairway to Scala




Wednesday, February 6, 13
Collections
                            (the gateway drug)




Wednesday, February 6, 13
Collections




Wednesday, February 6, 13
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;
                 }
           }




Wednesday, February 6, 13
public class Person {
             private final String name;
             private final String nick;
                                                      POJO
                                                      POSO*
                                                    *Actually just a Case Class
                 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) {
                            case class Person(name: String, nick: String)
                     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;
                 }
           }




Wednesday, February 6, 13
POSO*
                                         *Actually just a Case Class




                                                            val name: String

                            case class Person(name: String, nick: String)




Wednesday, February 6, 13
Case Classes

                val person = Person("Bruce Wayne", "Manbat") // whoops!
                val fixed = person.copy(nick = "Batman")
                     case class Person(name: String, nick: String)
                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?

Wednesday, February 6, 13
Scala Collections at Work
                              Given a list of People,
                            return all the Hero names.

        def heroNames(people: List[Person]): List[String] =
             people filter { _.isHero } map { _.name }




Wednesday, February 6, 13
Back to Android




Wednesday, February 6, 13
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;

                    // ...
                }




Wednesday, February 6, 13
What if... Scala?
                class class MakeANoteActivity ScalaActivity
                publicMakeANoteActivity extendsextends RoboActivity
                   with
                   implements View.OnClickListener
                           View.OnClickListener
                   with    PhotoOperations with CalibrationOperations
                {
                  val PhotoPath
                  public static final "picture_path"
                                    = String PHOTO_PATH = "picture_path";
                  val PhotoAttached = String PHOTO_ATTACHED = "photo_attached";
                  public static final "photo_attached"

                    lazy val sessionManager = SessionManager.get
                    @Inject SessionManager sessionManager;
                    lazy val locationManager = LocationManager.get
                    @Inject LocationHelper locationHelper;
                    @Inject PhotoHelper photoHelper;
                    @Inject Application context;

                    @Inject CalibrationHelper calibrationHelper;
                    lazy val attachPhoto = findView(TR.attach_photo)
                    lazy val noteText
                    @InjectView(R.id.attach_photo) Button attachPhoto;
                                         = findView(TR.note_text)
                    lazy val save
                    @InjectView(R.id.note_text) EditText noteText;
                                         = findView(TR.save_button)
                    lazy val dateText
                    @InjectView(R.id.save_button) Button save;
                                         = findView(TR.date)
                    lazy val share
                    @InjectView(R.id.date) TextView dateText;
                                         = findView(TR.share)
                    @InjectView(R.id.share) Button share;

                    val username = findResource[String](R.string.my_username)
                    @InjectResource(R.string.im_aircasting) String imAircasting;
                    val friends = findResource[List[String]](R.string.friends)
                    @InjectResource(R.string.share_with) String shareWith;

                    def...
                    // toastConferenceName() = "KrakDroid".toast()
                }




Wednesday, February 6, 13
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()
                }




Wednesday, February 6, 13
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()
                }




Wednesday, February 6, 13
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()
                }




Wednesday, February 6, 13
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()
                }




Wednesday, February 6, 13
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()
                }




Wednesday, February 6, 13
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()
                }




Wednesday, February 6, 13
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()
                }




Wednesday, February 6, 13
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)         Implicit Parameters
                    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()
                }




Wednesday, February 6, 13
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()
                }




Wednesday, February 6, 13
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()
                }




Wednesday, February 6, 13
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()
                }




Wednesday, February 6, 13
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()
                }




Wednesday, February 6, 13
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 Erasure


Wednesday, February 6, 13
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 Conversion

Wednesday, February 6, 13
Typed Resource




Wednesday, February 6, 13
Typed Resource = Better R




Wednesday, February 6, 13
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



                    Typed Resource = 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)          Typed Resource

                    val username = findResource[String](R.string.my_username)
                    val friends = findResource[List[String]](R.string.friends)

                    def toastConferenceName() = "KrakDroid".toast()
                }




Wednesday, February 6, 13
Typed Resource = Better R
             <TableLayout	
  android:id="@+id/login_table"
             	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  android:layout_gravity="center"
             	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  android:layout_height="wrap_content"
             	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  android:layout_width="wrap_content">


      case class TypedResource[T](id: Int)
      case class TypedLayout(id: Int)                                                         Wrappers




      object TR {
        val login_table = TypedResource[TableLayout](R.id.login_table)

          val workspaces = TypedResource[ExpandableListView](R.id.workspaces)

           val subtask_txt = TypedResource[TextView](R.id.subtask_txt)
          // ...

      }


Wednesday, February 6, 13
Typed Resource = Better R
             <TableLayout	
  android:id="@+id/login_table"
             	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  android:layout_gravity="center"
             	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  android:layout_height="wrap_content"
             	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  android:layout_width="wrap_content">


      case class TypedResource[T](id: Int)
      case class TypedLayout(id: Int)




      object TR {
        val login_table = TypedResource[TableLayout](R.id.login_table)

          val workspaces = TypedResource[ExpandableListView](R.id.workspaces)

           val subtask_txt = TypedResource[TextView](R.id.subtask_txt)
          // ...

      }


Wednesday, February 6, 13
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)

                    // ...
                }




Wednesday, February 6, 13
Types




            You always have the type information at hand.

                            (IntelliJ IDEA, ENSIME/Emacs, Eclipse)
                                 ⌘ SHIFT I
                                  ALT =




Wednesday, February 6, 13
Menus




Wednesday, February 6, 13
Menus = callbacks




Wednesday, February 6, 13
Java


          @Override
          public boolean onCreateOptionsMenu(Menu menu) {
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.game_menu, menu);
            return true;
          }



                            Menus = callbacks




Wednesday, February 6, 13
Menus = callbacks                             Java


          @Override
          public boolean onCreateOptionsMenu(Menu menu) {
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.game_menu, menu);
            return true;
          }


                            @Override
                            public boolean onOptionsItemSelected(MenuItem item) {
                                switch (item.getItemId()) {
                                    case R.id.new_game:
                                        newGame();
                                        return true;
                                    case R.id.help:
                                        showHelp();
                                        return true;
                                    default:
                                        return super.onOptionsItemSelected(item);
                                }
                            }

Wednesday, February 6, 13
Menus = callbacks                      Java

      public class AnActivity extends Activity {




                                public class AnActivity extends Activity {
      }




                                }
Wednesday, February 6, 13
Menus = callbacks                                  Java

      public class AnActivity extends Activity {




                                                                   th is?
                                                        to fix
                                            ways
                                       tyle
      }
                            Ja   v a-s       public class AnActivity extends Activity {




                                             }
Wednesday, February 6, 13
Delegate! Delegate! Delegate!                     Java



          public class GameMenu {
            public boolean onCreateOptionsMenu(Menu menu) { /*...*/ }
            public boolean onOptionsItemSelected(MenuItem item) { /*...*/ }
          }



                       public class AnActivity extends Activity {
                         GameMenu gameMenu = ...

                            public boolean onCreateOptionsMenu(Menu menu) {
                              return gameMenu.onCreateOptionsMenu(menu);
                            }

                            public boolean onOptionsItemSelected(MenuItem item) {
                              return gameMenu.onOptionsItemSelected(item)
                            }


                       }

Wednesday, February 6, 13
super class monster                     Java



          public abstract class WithGameMenuActivity extends Activity {
            public boolean onCreateOptionsMenu(Menu menu) { /*...*/ }
            public boolean onOptionsItemSelected(MenuItem item) { /*...*/ }
          }



           public class AnActivity extends WithGameMenuActivity {

           }




Wednesday, February 6, 13
Menus = callbacks                         Java

      public class AnActivity extends Activity {




                                                             th is?
                                                  to fix
                                            ays
                                 -styl   ew
                             cala    public class AnActivity extends Activity {
      }
                            S


                                     }
Wednesday, February 6, 13
Converting is simple
          @Override
          public boolean onCreateOptionsMenu(Menu menu) {
          override def onCreateOptionsMenu(Menu menu) =
            MenuInflater inflater = getMenuInflater();
            val inflater = getMenuInflater()
            inflater.inflate(R.menu.game_menu, menu);
                                               menu)
            return true;
            true
          }


                        @Override
                        override def onOptionsItemSelected(MenuItem item) =
                        public boolean onOptionsItemSelected(MenuItem item) {
                          item.getItemId() match {
                            switch (item.getItemId()) {
                            casecase R.id.new_game:
                                  R.id.new_game => newGame(); true
                            case R.id.help
                                     newGame(); => showHelp(); true
                            case _ return true; super.onOptionsItemSelected(item)
                                                 =>
                          }     case R.id.help:
                                     showHelp();
                                     return true;
                                default:
                                     return super.onOptionsItemSelected(item);
                            }
                        }

Wednesday, February 6, 13
The Menu Trait                               Scala


     trait GameMenu {


          override def onCreateOptionsMenu(Menu menu) = {
            val inflater = getMenuInflater()
            inflater.inflate(R.menu.game_menu, menu)
            true
          }                          Uhm... but we're not an Activity here!
          override def onOptionsItemSelected(MenuItem item) =
            item.getItemId() match {
              case R.id.new_game => newGame(); true
              case R.id.help     => showHelp(); true
              case _             => super.onOptionsItemSelected(item)
            }




     }


Wednesday, February 6, 13
The Menu Trait                             Scala


     trait GameMenu {
                                 Now we're sure "I'm in an Activity"
       this: Activity =>

          override def onCreateOptionsMenu(Menu menu) = {
            val inflater = getMenuInflater()
            inflater.inflate(R.menu.game_menu, menu)
            true
          }
          override def onOptionsItemSelected(MenuItem item) =
            item.getItemId() match {
              case R.id.new_game => newGame(); true
              case R.id.help     => showHelp(); true
              case _             => super.onOptionsItemSelected(item)
            }




     }


Wednesday, February 6, 13
The Menu Traits



                        class MyGame extends Activity with GameMenu
                                                      with SomeContextMenu




Wednesday, February 6, 13
An Implicit Context




Wednesday, February 6, 13
Passing around Context



                            Toast.makeText(ctx, msg, LENGTH_LONG).show();




                  Intent intent = new Intent(context, LocalService.class);




Wednesday, February 6, 13
An Implicit Context


                            def toastMyName(name: String, ctx: Context) {
                              import android.widget.Toast._

                                         Implicit != Explicit
                                makeText(ctx, msg, LENGTH_LONG).show()
                            }


                            toastMyName(”Siegfried”, getContext)




Wednesday, February 6, 13
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)




Wednesday, February 6, 13
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)




Wednesday, February 6, 13
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)




Wednesday, February 6, 13
An Implicit Context
                                       Implicit != Explicit


          def toastMyName(name: String)(implicit ctx: Context) {{
                  def toastMyName(name: String, ctx: Context)
            import android.widget.Toast._
                    import android.widget.Toast._

            makeText(ctx, msg, LENGTH_LONG).show()
                    makeText(ctx, msg, LENGTH_LONG).show()
          }       }


                            toastMyName(”Siegfried”, getContext)




Wednesday, February 6, 13
Implicit Parameters
                                Implicit != Explicit


          def toastMyName(name: String)(implicit ctx: Context) {
            import android.widget.Toast._

               makeText(ctx, msg, LENGTH_LONG).show()   Implicit Parameter
          }




Wednesday, February 6, 13
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)




Wednesday, February 6, 13
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!




Wednesday, February 6, 13
Implicit Conversions




Wednesday, February 6, 13
Implicit Conversions



                                Implicit != Explicit




Wednesday, February 6, 13
Implicit Conversions
                                 Implicit != Explicit
                                                Implicit Context, remember?

                             toastMyName("Siegfried")

                                 What if we could...


                               "Siegfried".toast()




Wednesday, February 6, 13
Implicit Conversions
                                    Implicit != Explicit
            Decorator
                                                                 Constructor
                            class Toastable(msg: String) {
                              def toast()(implicit ctx: Context) = ???
                            }




                      new Toastable("Hello!").toast()




Wednesday, February 6, 13
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()




Wednesday, February 6, 13
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)
              }                                 "Hello!".toast()


               class ExampleActivity
                 extends Activity
                 with ImplicitContext
                 with ScalaToasts



Wednesday, February 6, 13
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 ScalaToasts



Wednesday, February 6, 13
Implicit Conversions




Wednesday, February 6, 13
And there’s more!




Wednesday, February 6, 13
Simple Threading

                            implicit val handler = new Handler



                            inUiThread {
                              // ...
                            }


                            inFutureWithProgressDialog(timeout = 10.seconds) {
                              // ...
                            }                          Implicit Conversion on Int


                                           Not a replacement for proper design




Wednesday, February 6, 13
on___
                      button.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                          // ...
                        }
                      });




                            button onClick { view =>
                               // ...
                            }



Wednesday, February 6, 13
SharedPreferences

                     KanbaneryPreferences.projectId = 1337



            val name: Option[Long] = KanbaneryPreferences.projectId




Wednesday, February 6, 13
SharedPreferences
                   object KanbaneryPreferences {

                     private val KeyLogin   = "login"

                       private def sharedPreferences(implicit ctx: Context) = ???

                       def login(implicit ctx: Context) =
                         sharedPreferences.getString(KeyLogin, "")




Wednesday, February 6, 13
SharedPreferences
                   object KanbaneryPreferences {

                     private val KeyLogin   = "login"

                       private def sharedPreferences(implicit ctx: Context) = ???




                       def login_=(number: String)(implicit ctx: Context) {
                         withSharedPreferencesEditor {
                           _.putString(KeyLogin, number)
                         }

                       }




Wednesday, February 6, 13
SharedPreferences
                   object KanbaneryPreferences {

                       private val KeyLogin   = "login"

                       private def sharedPreferences(implicit ctx: Context) = ???




                       def login_=(number: String)(implicit ctx: Context) {
                         withSharedPreferencesEditor {
                           _.putString(KeyLogin, number)
                         }

                   }




Wednesday, February 6, 13
SharedPreferences

                   def withSharedPreferencesEditor
                       (block: SharedPreferences.Editor => Unit)
                       (implicit ctx: Context) {

                       val editor = sharedPreferences.edit()

                       block(editor)

                       editor.commit()
                   }



                                         withSharedPreferencesEditor {
                                           _.putString(KeyLogin, number)
                                         }



Wednesday, February 6, 13
Let me warn you...



                            Scala is addictive.


Wednesday, February 6, 13
Let me warn you...



                            Scala is addictive.


Wednesday, February 6, 13
Scala is addictive.




Wednesday, February 6, 13
Scala my Android?


Wednesday, February 6, 13
Scala my Android?


Wednesday, February 6, 13
Scala my Android?

                                - Android Library projects?
                              - Not "Java level" IDE support?
                                       - Debugging?
                                   - ProGuard-ing time?
                                - Increased cognitive load?




Wednesday, February 6, 13
Scala my Android?

                                 + No boilerplate
                              + Focus on the app/domain
                               + No need for reflection
                                + Less cognitive load?
                                   + Scala libraries
                                  + SBT (build tool)



Wednesday, February 6, 13
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.*
                               • Fully Open Source
                               • New version soon! Pull and play with it!
                            • Scaloid https://github.com/pocorall/scaloid
                               • Many of the things we've seen, a bit more; some awesome, some less



                                                                       Mailing lists rock!



Wednesday, February 6, 13
I love feedback! <3

                                                       Konrad Malawski / @ktosopl
                                                  GeeCON / GDG / PJUG / KSUG / SCKRK
                                                          JFokus 06.02.2013
Wednesday, February 6, 13

More Related Content

PPT
Ruby conf2012
PPTX
Android
PDF
[Tokyo Scala User Group] Akka Streams & Reactive Streams (0.7)
PDF
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
PDF
Reactive Streams / Akka Streams - GeeCON Prague 2014
PDF
Akka-chan's Survival Guide for the Streaming World
PDF
Functor, Apply, Applicative And Monad
PPTX
Refactoring Design Patterns the Functional Way (in Scala)
Ruby conf2012
Android
[Tokyo Scala User Group] Akka Streams & Reactive Streams (0.7)
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Reactive Streams / Akka Streams - GeeCON Prague 2014
Akka-chan's Survival Guide for the Streaming World
Functor, Apply, Applicative And Monad
Refactoring Design Patterns the Functional Way (in Scala)

Viewers also liked (20)

PDF
Scala Implicits - Not to be feared
PDF
TDD drogą do oświecenia w Scali
PDF
Git tak po prostu (SFI version)
PDF
Android at-xsolve
PDF
Scala dsls-dissecting-and-implementing-rogue
PDF
Open soucerers - jak zacząć swoją przygodę z open source
PDF
JavaOne 2013: Java 8 - The Good Parts
PDF
Scalding - the not-so-basics @ ScalaDays 2014
PDF
HBase RowKey design for Akka Persistence
PDF
Ebay legacy-code-retreat
PDF
Need for Async: Hot pursuit for scalable applications
PDF
2014 akka-streams-tokyo-japanese
PDF
KrakDroid: Scala on Android
PDF
Scalding - Hadoop Word Count in LESS than 70 lines of code
PDF
100th SCKRK Meeting - best software engineering papers of 5 years of SCKRK
PDF
Disrupt 2 Grow - Devoxx 2013
PDF
The things we don't see – stories of Software, Scala and Akka
PDF
[Japanese] How Reactive Streams and Akka Streams change the JVM Ecosystem @ R...
PDF
The Need for Async @ ScalaWorld
PDF
Akka Streams in Action @ ScalaDays Berlin 2016
Scala Implicits - Not to be feared
TDD drogą do oświecenia w Scali
Git tak po prostu (SFI version)
Android at-xsolve
Scala dsls-dissecting-and-implementing-rogue
Open soucerers - jak zacząć swoją przygodę z open source
JavaOne 2013: Java 8 - The Good Parts
Scalding - the not-so-basics @ ScalaDays 2014
HBase RowKey design for Akka Persistence
Ebay legacy-code-retreat
Need for Async: Hot pursuit for scalable applications
2014 akka-streams-tokyo-japanese
KrakDroid: Scala on Android
Scalding - Hadoop Word Count in LESS than 70 lines of code
100th SCKRK Meeting - best software engineering papers of 5 years of SCKRK
Disrupt 2 Grow - Devoxx 2013
The things we don't see – stories of Software, Scala and Akka
[Japanese] How Reactive Streams and Akka Streams change the JVM Ecosystem @ R...
The Need for Async @ ScalaWorld
Akka Streams in Action @ ScalaDays Berlin 2016
Ad

Similar to Android my Scala @ JFokus 2013 (20)

PPTX
Lesson 3
PPT
Android Application Development Programming
PDF
Android Programming For Developers John Horton Helder Vasconcelos
PPTX
Android Study Jams - Session 3
KEY
Getting the most out of Java [Nordic Coding-2010]
PDF
Building More with Less
PDF
Effective Scala @ Jfokus
PPTX
Android Study Jams - Session 2
PDF
OpenThink Labs Training : Diving into Java, The Head First Way
PPTX
Android Study Jams - Session 1
PPTX
Lecture #3 activities and intents
PDF
Stanford session
PPTX
Android study jams - new to programming track sessions 2
PPTX
DSC ASEB Android Study Jams 2020: New to Programming 3
PPTX
[EXTERNAL] Android Basics Sessions 1 _ 2 - Android Study Jams.pptx
PDF
Android training in cochin android training in kochi android training in kera...
PDF
Kotlin techtalk
PPTX
Android User Interface Tutorial: DatePicker, TimePicker & Spinner
PDF
[Android] Widget Event Handling
PDF
Angular.js - JS Camp UKraine 2013
Lesson 3
Android Application Development Programming
Android Programming For Developers John Horton Helder Vasconcelos
Android Study Jams - Session 3
Getting the most out of Java [Nordic Coding-2010]
Building More with Less
Effective Scala @ Jfokus
Android Study Jams - Session 2
OpenThink Labs Training : Diving into Java, The Head First Way
Android Study Jams - Session 1
Lecture #3 activities and intents
Stanford session
Android study jams - new to programming track sessions 2
DSC ASEB Android Study Jams 2020: New to Programming 3
[EXTERNAL] Android Basics Sessions 1 _ 2 - Android Study Jams.pptx
Android training in cochin android training in kochi android training in kera...
Kotlin techtalk
Android User Interface Tutorial: DatePicker, TimePicker & Spinner
[Android] Widget Event Handling
Angular.js - JS Camp UKraine 2013
Ad

More from Konrad Malawski (16)

PDF
Networks and Types - the Future of Akka @ ScalaDays NYC 2018
PDF
Akka Typed (quick talk) - JFokus 2018
PDF
ScalaSwarm 2017 Keynote: Tough this be madness yet theres method in't
PDF
State of Akka 2017 - The best is yet to come
PDF
Building a Reactive System with Akka - Workshop @ O'Reilly SAConf NYC
PDF
Reactive integrations with Akka Streams
PDF
Not Only Streams for Akademia JLabs
PDF
Reactive Streams, j.u.concurrent & Beyond!
PDF
End to End Akka Streams / Reactive Streams - from Business to Socket
PDF
The Cloud-natives are RESTless @ JavaOne
PDF
Krakow communities @ 2016
PDF
Zen of Akka
PDF
How Reactive Streams & Akka Streams change the JVM Ecosystem
PDF
Reactive Stream Processing with Akka Streams
PDF
Distributed Consensus A.K.A. "What do we eat for lunch?"
PDF
DDDing Tools = Akka Persistence
Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Akka Typed (quick talk) - JFokus 2018
ScalaSwarm 2017 Keynote: Tough this be madness yet theres method in't
State of Akka 2017 - The best is yet to come
Building a Reactive System with Akka - Workshop @ O'Reilly SAConf NYC
Reactive integrations with Akka Streams
Not Only Streams for Akademia JLabs
Reactive Streams, j.u.concurrent & Beyond!
End to End Akka Streams / Reactive Streams - from Business to Socket
The Cloud-natives are RESTless @ JavaOne
Krakow communities @ 2016
Zen of Akka
How Reactive Streams & Akka Streams change the JVM Ecosystem
Reactive Stream Processing with Akka Streams
Distributed Consensus A.K.A. "What do we eat for lunch?"
DDDing Tools = Akka Persistence

Android my Scala @ JFokus 2013

  • 1. Scala Android Konrad Malawski / @ktosopl GeeCON / GDG / PJUG / KSUG / SCKRK JFokus 06.02.2013 Wednesday, February 6, 13
  • 2. Konrad Malawski twitter: ktosopl Wednesday, February 6, 13
  • 3. This will be... Wednesday, February 6, 13
  • 4. This will Not be... Wednesday, February 6, 13
  • 5. This will Not be... Wednesday, February 6, 13
  • 6. This will Not be... a Java rant, about app design. Wednesday, February 6, 13
  • 7. This will be about... Wednesday, February 6, 13
  • 8. This will be about... Wednesday, February 6, 13
  • 9. This will be about... shifting cognitive load writing less code fokus on goals, not means Wednesday, February 6, 13
  • 12. Scala is Simple , but Hard. Wednesday, February 6, 13
  • 13. Scala is Simple. Wednesday, February 6, 13
  • 14. 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/ Wednesday, February 6, 13
  • 15. Scala is A Functional, Object Oriented, Statically Typed, Scalable, Language... ...running on the JVM and DVM! Wednesday, February 6, 13
  • 17. 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); // ... } } Wednesday, February 6, 13
  • 18. 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); // ... } } Wednesday, February 6, 13
  • 19. 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); // ... } } Wednesday, February 6, 13
  • 20. 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! Wednesday, February 6, 13
  • 21. Robo Guice So many public class MakeANoteActivity extends RoboActivity 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; // ... } Wednesday, February 6, 13
  • 22. Robo Guice public class MakeANoteActivity extends RoboActivity implements View.OnClickListener { Guice is eager. public static final String PHOTO_PATH Startup can take a few seconds! = "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; // ... } Wednesday, February 6, 13
  • 23. 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; // ... } Wednesday, February 6, 13
  • 25. Collections (the gateway drug) Wednesday, February 6, 13
  • 27. 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; } } Wednesday, February 6, 13
  • 28. public class Person { private final String name; private final String nick; POJO POSO* *Actually just a Case Class 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) { case class Person(name: String, nick: String) 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; } } Wednesday, February 6, 13
  • 29. POSO* *Actually just a Case Class val name: String case class Person(name: String, nick: String) Wednesday, February 6, 13
  • 30. Case Classes val person = Person("Bruce Wayne", "Manbat") // whoops! val fixed = person.copy(nick = "Batman") case class Person(name: String, nick: String) 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? Wednesday, February 6, 13
  • 31. Scala Collections at Work Given a list of People, return all the Hero names. def heroNames(people: List[Person]): List[String] = people filter { _.isHero } map { _.name } Wednesday, February 6, 13
  • 32. Back to Android Wednesday, February 6, 13
  • 33. 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; // ... } Wednesday, February 6, 13
  • 34. What if... Scala? class class MakeANoteActivity ScalaActivity publicMakeANoteActivity extendsextends RoboActivity with implements View.OnClickListener View.OnClickListener with PhotoOperations with CalibrationOperations { val PhotoPath public static final "picture_path" = String PHOTO_PATH = "picture_path"; val PhotoAttached = String PHOTO_ATTACHED = "photo_attached"; public static final "photo_attached" lazy val sessionManager = SessionManager.get @Inject SessionManager sessionManager; lazy val locationManager = LocationManager.get @Inject LocationHelper locationHelper; @Inject PhotoHelper photoHelper; @Inject Application context; @Inject CalibrationHelper calibrationHelper; lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText @InjectView(R.id.attach_photo) Button attachPhoto; = findView(TR.note_text) lazy val save @InjectView(R.id.note_text) EditText noteText; = findView(TR.save_button) lazy val dateText @InjectView(R.id.save_button) Button save; = findView(TR.date) lazy val share @InjectView(R.id.date) TextView dateText; = findView(TR.share) @InjectView(R.id.share) Button share; val username = findResource[String](R.string.my_username) @InjectResource(R.string.im_aircasting) String imAircasting; val friends = findResource[List[String]](R.string.friends) @InjectResource(R.string.share_with) String shareWith; def... // toastConferenceName() = "KrakDroid".toast() } Wednesday, February 6, 13
  • 35. 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() } Wednesday, February 6, 13
  • 36. 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() } Wednesday, February 6, 13
  • 37. 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() } Wednesday, February 6, 13
  • 38. 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() } Wednesday, February 6, 13
  • 39. 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() } Wednesday, February 6, 13
  • 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 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() } Wednesday, February 6, 13
  • 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 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() } Wednesday, February 6, 13
  • 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 Needs Context lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) Implicit Parameters 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() } Wednesday, February 6, 13
  • 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?!? 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() } Wednesday, February 6, 13
  • 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) val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() } Wednesday, February 6, 13
  • 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 = 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() } Wednesday, February 6, 13
  • 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 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() } Wednesday, February 6, 13
  • 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 = 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 Erasure Wednesday, February 6, 13
  • 48. 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 Conversion Wednesday, February 6, 13
  • 50. Typed Resource = Better R Wednesday, February 6, 13
  • 51. 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 Typed Resource = 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) Typed Resource val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends) def toastConferenceName() = "KrakDroid".toast() } Wednesday, February 6, 13
  • 52. Typed Resource = Better R <TableLayout  android:id="@+id/login_table"                                  android:layout_gravity="center"                                  android:layout_height="wrap_content"                                  android:layout_width="wrap_content"> case class TypedResource[T](id: Int) case class TypedLayout(id: Int) Wrappers object TR { val login_table = TypedResource[TableLayout](R.id.login_table) val workspaces = TypedResource[ExpandableListView](R.id.workspaces) val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ... } Wednesday, February 6, 13
  • 53. Typed Resource = Better R <TableLayout  android:id="@+id/login_table"                                  android:layout_gravity="center"                                  android:layout_height="wrap_content"                                  android:layout_width="wrap_content"> case class TypedResource[T](id: Int) case class TypedLayout(id: Int) object TR { val login_table = TypedResource[TableLayout](R.id.login_table) val workspaces = TypedResource[ExpandableListView](R.id.workspaces) val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ... } Wednesday, February 6, 13
  • 54. 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) // ... } Wednesday, February 6, 13
  • 55. Types You always have the type information at hand. (IntelliJ IDEA, ENSIME/Emacs, Eclipse) ⌘ SHIFT I ALT = Wednesday, February 6, 13
  • 58. Java @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.game_menu, menu); return true; } Menus = callbacks Wednesday, February 6, 13
  • 59. Menus = callbacks Java @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.game_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.new_game: newGame(); return true; case R.id.help: showHelp(); return true; default: return super.onOptionsItemSelected(item); } } Wednesday, February 6, 13
  • 60. Menus = callbacks Java public class AnActivity extends Activity { public class AnActivity extends Activity { } } Wednesday, February 6, 13
  • 61. Menus = callbacks Java public class AnActivity extends Activity { th is? to fix ways tyle } Ja v a-s public class AnActivity extends Activity { } Wednesday, February 6, 13
  • 62. Delegate! Delegate! Delegate! Java public class GameMenu { public boolean onCreateOptionsMenu(Menu menu) { /*...*/ } public boolean onOptionsItemSelected(MenuItem item) { /*...*/ } } public class AnActivity extends Activity { GameMenu gameMenu = ... public boolean onCreateOptionsMenu(Menu menu) { return gameMenu.onCreateOptionsMenu(menu); } public boolean onOptionsItemSelected(MenuItem item) { return gameMenu.onOptionsItemSelected(item) } } Wednesday, February 6, 13
  • 63. super class monster Java public abstract class WithGameMenuActivity extends Activity { public boolean onCreateOptionsMenu(Menu menu) { /*...*/ } public boolean onOptionsItemSelected(MenuItem item) { /*...*/ } } public class AnActivity extends WithGameMenuActivity { } Wednesday, February 6, 13
  • 64. Menus = callbacks Java public class AnActivity extends Activity { th is? to fix ays -styl ew cala public class AnActivity extends Activity { } S } Wednesday, February 6, 13
  • 65. Converting is simple @Override public boolean onCreateOptionsMenu(Menu menu) { override def onCreateOptionsMenu(Menu menu) = MenuInflater inflater = getMenuInflater(); val inflater = getMenuInflater() inflater.inflate(R.menu.game_menu, menu); menu) return true; true } @Override override def onOptionsItemSelected(MenuItem item) = public boolean onOptionsItemSelected(MenuItem item) { item.getItemId() match { switch (item.getItemId()) { casecase R.id.new_game: R.id.new_game => newGame(); true case R.id.help newGame(); => showHelp(); true case _ return true; super.onOptionsItemSelected(item) => } case R.id.help: showHelp(); return true; default: return super.onOptionsItemSelected(item); } } Wednesday, February 6, 13
  • 66. The Menu Trait Scala trait GameMenu { override def onCreateOptionsMenu(Menu menu) = { val inflater = getMenuInflater() inflater.inflate(R.menu.game_menu, menu) true } Uhm... but we're not an Activity here! override def onOptionsItemSelected(MenuItem item) = item.getItemId() match { case R.id.new_game => newGame(); true case R.id.help => showHelp(); true case _ => super.onOptionsItemSelected(item) } } Wednesday, February 6, 13
  • 67. The Menu Trait Scala trait GameMenu { Now we're sure "I'm in an Activity" this: Activity => override def onCreateOptionsMenu(Menu menu) = { val inflater = getMenuInflater() inflater.inflate(R.menu.game_menu, menu) true } override def onOptionsItemSelected(MenuItem item) = item.getItemId() match { case R.id.new_game => newGame(); true case R.id.help => showHelp(); true case _ => super.onOptionsItemSelected(item) } } Wednesday, February 6, 13
  • 68. The Menu Traits class MyGame extends Activity with GameMenu with SomeContextMenu Wednesday, February 6, 13
  • 70. Passing around Context Toast.makeText(ctx, msg, LENGTH_LONG).show(); Intent intent = new Intent(context, LocalService.class); Wednesday, February 6, 13
  • 71. An Implicit Context def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ Implicit != Explicit makeText(ctx, msg, LENGTH_LONG).show() } toastMyName(”Siegfried”, getContext) Wednesday, February 6, 13
  • 72. 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) Wednesday, February 6, 13
  • 73. 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) Wednesday, February 6, 13
  • 74. 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) Wednesday, February 6, 13
  • 75. An Implicit Context Implicit != Explicit def toastMyName(name: String)(implicit ctx: Context) {{ def toastMyName(name: String, ctx: Context) import android.widget.Toast._ import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() makeText(ctx, msg, LENGTH_LONG).show() } } toastMyName(”Siegfried”, getContext) Wednesday, February 6, 13
  • 76. Implicit Parameters Implicit != Explicit def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show() Implicit Parameter } Wednesday, February 6, 13
  • 77. 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) Wednesday, February 6, 13
  • 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! Wednesday, February 6, 13
  • 80. Implicit Conversions Implicit != Explicit Wednesday, February 6, 13
  • 81. Implicit Conversions Implicit != Explicit Implicit Context, remember? toastMyName("Siegfried") What if we could... "Siegfried".toast() Wednesday, February 6, 13
  • 82. Implicit Conversions Implicit != Explicit Decorator Constructor class Toastable(msg: String) { def toast()(implicit ctx: Context) = ??? } new Toastable("Hello!").toast() Wednesday, February 6, 13
  • 83. 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() Wednesday, February 6, 13
  • 84. 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) } "Hello!".toast() class ExampleActivity extends Activity with ImplicitContext with ScalaToasts Wednesday, February 6, 13
  • 85. 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 ScalaToasts Wednesday, February 6, 13
  • 88. Simple Threading implicit val handler = new Handler inUiThread { // ... } inFutureWithProgressDialog(timeout = 10.seconds) { // ... } Implicit Conversion on Int Not a replacement for proper design Wednesday, February 6, 13
  • 89. on___ button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // ... } }); button onClick { view => // ... } Wednesday, February 6, 13
  • 90. SharedPreferences KanbaneryPreferences.projectId = 1337 val name: Option[Long] = KanbaneryPreferences.projectId Wednesday, February 6, 13
  • 91. SharedPreferences object KanbaneryPreferences { private val KeyLogin = "login" private def sharedPreferences(implicit ctx: Context) = ??? def login(implicit ctx: Context) = sharedPreferences.getString(KeyLogin, "") Wednesday, February 6, 13
  • 92. SharedPreferences object KanbaneryPreferences { private val KeyLogin = "login" private def sharedPreferences(implicit ctx: Context) = ??? def login_=(number: String)(implicit ctx: Context) { withSharedPreferencesEditor { _.putString(KeyLogin, number) } } Wednesday, February 6, 13
  • 93. SharedPreferences object KanbaneryPreferences { private val KeyLogin = "login" private def sharedPreferences(implicit ctx: Context) = ??? def login_=(number: String)(implicit ctx: Context) { withSharedPreferencesEditor { _.putString(KeyLogin, number) } } Wednesday, February 6, 13
  • 94. SharedPreferences def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) { val editor = sharedPreferences.edit() block(editor) editor.commit() } withSharedPreferencesEditor { _.putString(KeyLogin, number) } Wednesday, February 6, 13
  • 95. Let me warn you... Scala is addictive. Wednesday, February 6, 13
  • 96. Let me warn you... Scala is addictive. Wednesday, February 6, 13
  • 100. Scala my Android? - Android Library projects? - Not "Java level" IDE support? - Debugging? - ProGuard-ing time? - Increased cognitive load? Wednesday, February 6, 13
  • 101. Scala my Android? + No boilerplate + Focus on the app/domain + No need for reflection + Less cognitive load? + Scala libraries + SBT (build tool) Wednesday, February 6, 13
  • 102. 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.* • Fully Open Source • New version soon! Pull and play with it! • Scaloid https://github.com/pocorall/scaloid • Many of the things we've seen, a bit more; some awesome, some less Mailing lists rock! Wednesday, February 6, 13
  • 103. I love feedback! <3 Konrad Malawski / @ktosopl GeeCON / GDG / PJUG / KSUG / SCKRK JFokus 06.02.2013 Wednesday, February 6, 13