SlideShare una empresa de Scribd logo
1 de 103
Descargar para leer sin conexión
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

Más contenido relacionado

Destacado

Scala Implicits - Not to be feared
Scala Implicits - Not to be fearedScala Implicits - Not to be feared
Scala Implicits - Not to be fearedDerek Wyatt
 
TDD drogą do oświecenia w Scali
TDD drogą do oświecenia w ScaliTDD drogą do oświecenia w Scali
TDD drogą do oświecenia w ScaliKonrad Malawski
 
Git tak po prostu (SFI version)
Git tak po prostu (SFI version)Git tak po prostu (SFI version)
Git tak po prostu (SFI version)Konrad Malawski
 
Scala dsls-dissecting-and-implementing-rogue
Scala dsls-dissecting-and-implementing-rogueScala dsls-dissecting-and-implementing-rogue
Scala dsls-dissecting-and-implementing-rogueKonrad Malawski
 
Open soucerers - jak zacząć swoją przygodę z open source
Open soucerers - jak zacząć swoją przygodę z open sourceOpen soucerers - jak zacząć swoją przygodę z open source
Open soucerers - jak zacząć swoją przygodę z open sourceKonrad Malawski
 
JavaOne 2013: Java 8 - The Good Parts
JavaOne 2013: Java 8 - The Good PartsJavaOne 2013: Java 8 - The Good Parts
JavaOne 2013: Java 8 - The Good PartsKonrad Malawski
 
Scalding - the not-so-basics @ ScalaDays 2014
Scalding - the not-so-basics @ ScalaDays 2014Scalding - the not-so-basics @ ScalaDays 2014
Scalding - the not-so-basics @ ScalaDays 2014Konrad Malawski
 
HBase RowKey design for Akka Persistence
HBase RowKey design for Akka PersistenceHBase RowKey design for Akka Persistence
HBase RowKey design for Akka PersistenceKonrad Malawski
 
Ebay legacy-code-retreat
Ebay legacy-code-retreatEbay legacy-code-retreat
Ebay legacy-code-retreatKonrad Malawski
 
Need for Async: Hot pursuit for scalable applications
Need for Async: Hot pursuit for scalable applicationsNeed for Async: Hot pursuit for scalable applications
Need for Async: Hot pursuit for scalable applicationsKonrad Malawski
 
2014 akka-streams-tokyo-japanese
2014 akka-streams-tokyo-japanese2014 akka-streams-tokyo-japanese
2014 akka-streams-tokyo-japaneseKonrad Malawski
 
KrakDroid: Scala on Android
KrakDroid: Scala on AndroidKrakDroid: Scala on Android
KrakDroid: Scala on AndroidKonrad Malawski
 
Scalding - Hadoop Word Count in LESS than 70 lines of code
Scalding - Hadoop Word Count in LESS than 70 lines of codeScalding - Hadoop Word Count in LESS than 70 lines of code
Scalding - Hadoop Word Count in LESS than 70 lines of codeKonrad Malawski
 
100th SCKRK Meeting - best software engineering papers of 5 years of SCKRK
100th SCKRK Meeting - best software engineering papers of 5 years of SCKRK100th SCKRK Meeting - best software engineering papers of 5 years of SCKRK
100th SCKRK Meeting - best software engineering papers of 5 years of SCKRKKonrad Malawski
 
Disrupt 2 Grow - Devoxx 2013
Disrupt 2 Grow - Devoxx 2013Disrupt 2 Grow - Devoxx 2013
Disrupt 2 Grow - Devoxx 2013Konrad Malawski
 
The things we don't see – stories of Software, Scala and Akka
The things we don't see – stories of Software, Scala and AkkaThe things we don't see – stories of Software, Scala and Akka
The things we don't see – stories of Software, Scala and AkkaKonrad Malawski
 
[Japanese] How Reactive Streams and Akka Streams change the JVM Ecosystem @ R...
[Japanese] How Reactive Streams and Akka Streams change the JVM Ecosystem @ R...[Japanese] How Reactive Streams and Akka Streams change the JVM Ecosystem @ R...
[Japanese] How Reactive Streams and Akka Streams change the JVM Ecosystem @ R...Konrad Malawski
 
The Need for Async @ ScalaWorld
The Need for Async @ ScalaWorldThe Need for Async @ ScalaWorld
The Need for Async @ ScalaWorldKonrad Malawski
 
Akka Streams in Action @ ScalaDays Berlin 2016
Akka Streams in Action @ ScalaDays Berlin 2016Akka Streams in Action @ ScalaDays Berlin 2016
Akka Streams in Action @ ScalaDays Berlin 2016Konrad Malawski
 

Destacado (20)

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

Similar a Android my Scala @ JFokus 2013

What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...Richard McIntyre
 
Building More with Less
Building More with LessBuilding More with Less
Building More with Lessdonnfelker
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android InfrastructureAlexey Buzdin
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android InfrastructureC.T.Co
 
GitHub halp app - Minimizing platform-specific code with MVVM - Justin Spahr-...
GitHub halp app - Minimizing platform-specific code with MVVM - Justin Spahr-...GitHub halp app - Minimizing platform-specific code with MVVM - Justin Spahr-...
GitHub halp app - Minimizing platform-specific code with MVVM - Justin Spahr-...Xamarin
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)Jose Manuel Pereira Garcia
 
Saindo da zona de conforto… resolvi aprender android
Saindo da zona de conforto… resolvi aprender androidSaindo da zona de conforto… resolvi aprender android
Saindo da zona de conforto… resolvi aprender androidDaniel Baccin
 
How to code to code less
How to code to code lessHow to code to code less
How to code to code lessAnton Novikau
 
FITC 2013 - The Technical Learning Curve
FITC 2013 - The Technical Learning CurveFITC 2013 - The Technical Learning Curve
FITC 2013 - The Technical Learning CurveLittle Miss Robot
 
Android basic 4 Navigation Drawer
Android basic 4 Navigation DrawerAndroid basic 4 Navigation Drawer
Android basic 4 Navigation DrawerEakapong Kattiya
 
SV-ios-objc-to-swift
SV-ios-objc-to-swiftSV-ios-objc-to-swift
SV-ios-objc-to-swiftRandy Scovil
 
Scala on-android
Scala on-androidScala on-android
Scala on-androidMax Lv
 
Building native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahBuilding native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahNick Plante
 
Introduction to Spring Boot.pdf
Introduction to Spring Boot.pdfIntroduction to Spring Boot.pdf
Introduction to Spring Boot.pdfShaiAlmog1
 
JSAnkara Swift v React Native
JSAnkara Swift v React NativeJSAnkara Swift v React Native
JSAnkara Swift v React NativeMuhammed Demirci
 
Introduction to JavaScript
Introduction to JavaScriptIntroduction to JavaScript
Introduction to JavaScriptzachwise
 
Android Bootstrap
Android BootstrapAndroid Bootstrap
Android Bootstrapdonnfelker
 
Teaching Programming Online
Teaching Programming OnlineTeaching Programming Online
Teaching Programming OnlinePamela Fox
 
Hacking for Fun and Profit (Mostly for Fun). AnDevCon Boston
Hacking for Fun and Profit (Mostly for Fun). AnDevCon BostonHacking for Fun and Profit (Mostly for Fun). AnDevCon Boston
Hacking for Fun and Profit (Mostly for Fun). AnDevCon BostonApkudo
 

Similar a Android my Scala @ JFokus 2013 (20)

What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...
 
Building More with Less
Building More with LessBuilding More with Less
Building More with Less
 
Scalding for Hadoop
Scalding for HadoopScalding for Hadoop
Scalding for Hadoop
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
 
GitHub halp app - Minimizing platform-specific code with MVVM - Justin Spahr-...
GitHub halp app - Minimizing platform-specific code with MVVM - Justin Spahr-...GitHub halp app - Minimizing platform-specific code with MVVM - Justin Spahr-...
GitHub halp app - Minimizing platform-specific code with MVVM - Justin Spahr-...
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
 
Saindo da zona de conforto… resolvi aprender android
Saindo da zona de conforto… resolvi aprender androidSaindo da zona de conforto… resolvi aprender android
Saindo da zona de conforto… resolvi aprender android
 
How to code to code less
How to code to code lessHow to code to code less
How to code to code less
 
FITC 2013 - The Technical Learning Curve
FITC 2013 - The Technical Learning CurveFITC 2013 - The Technical Learning Curve
FITC 2013 - The Technical Learning Curve
 
Android basic 4 Navigation Drawer
Android basic 4 Navigation DrawerAndroid basic 4 Navigation Drawer
Android basic 4 Navigation Drawer
 
SV-ios-objc-to-swift
SV-ios-objc-to-swiftSV-ios-objc-to-swift
SV-ios-objc-to-swift
 
Scala on-android
Scala on-androidScala on-android
Scala on-android
 
Building native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahBuilding native Android applications with Mirah and Pindah
Building native Android applications with Mirah and Pindah
 
Introduction to Spring Boot.pdf
Introduction to Spring Boot.pdfIntroduction to Spring Boot.pdf
Introduction to Spring Boot.pdf
 
JSAnkara Swift v React Native
JSAnkara Swift v React NativeJSAnkara Swift v React Native
JSAnkara Swift v React Native
 
Introduction to JavaScript
Introduction to JavaScriptIntroduction to JavaScript
Introduction to JavaScript
 
Android Bootstrap
Android BootstrapAndroid Bootstrap
Android Bootstrap
 
Teaching Programming Online
Teaching Programming OnlineTeaching Programming Online
Teaching Programming Online
 
Hacking for Fun and Profit (Mostly for Fun). AnDevCon Boston
Hacking for Fun and Profit (Mostly for Fun). AnDevCon BostonHacking for Fun and Profit (Mostly for Fun). AnDevCon Boston
Hacking for Fun and Profit (Mostly for Fun). AnDevCon Boston
 

Más de Konrad Malawski

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

Más de Konrad Malawski (16)

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