Upload
konrad-malawski
View
2.906
Download
2
Tags:
Embed Size (px)
DESCRIPTION
A revamped talk about #scala programming on #android. Presentation given at krakdroid 2012. http://krakdroid.pl
Citation preview
Scala Android
Konrad Malawski / @ktosoplGDG / PJUG / KSUG / SCKRK
KrakDroid 14.12.2012Sunday, December 16, 12
Sunday, December 16, 12
Sunday, December 16, 12
Scala is
Sunday, December 16, 12
Scala is
Sunday, December 16, 12
Scala is
Sunday, December 16, 12
Scala is
Sunday, December 16, 12
Scala is
Simple
Sunday, December 16, 12
Scala is
Simple , but Hard.
Sunday, December 16, 12
Scala is Simple.
Sunday, December 16, 12
Scala is Simple.
Sunday, December 16, 12
Scala is Hard.
http://apocalisp.wordpress.com/2010/10/26/type-level-programming
-in-scala-part-7-natural-transformation%C2%A0literals/Sunday, December 16, 12
Scala is Hard.object Param {
implicit def pToT[A[_], B[_]](f: (p: Param[A]) => B[p.T]): A~>B = new (A ~> B) { def apply[s](a: A[s]): B[s] = { val v: Param[A] { type T = s} = new Param[A] { type T = s def in = a } f(v) } }
}
http://apocalisp.wordpress.com/2010/10/26/type-level-programming
-in-scala-part-7-natural-transformation%C2%A0literals/Sunday, December 16, 12
Scala is
Sunday, December 16, 12
Scala is
A Functional,
Sunday, December 16, 12
Scala is
A Functional,Object Oriented,
Sunday, December 16, 12
Scala is
A Functional,Object Oriented,Statically Typed,
Sunday, December 16, 12
Scala is
A Functional,Object Oriented,Statically Typed,
Scalable,
Sunday, December 16, 12
Scala is
A Functional,Object Oriented,Statically Typed,
Scalable,Language...
Sunday, December 16, 12
Scala is
A Functional,Object Oriented,Statically Typed,
Scalable,Language...
...running on the JVM and DVM!
Sunday, December 16, 12
Android
Sunday, December 16, 12
findViewByIdpublic class MyActivity extends Activity {
ListView comments; Button newComment;
@Override void onCreate(Bundle bundle) { super.onCreate(bundle); comments = (ListView) findViewById(R.id.comments); newComment = (Button) findViewById(R.id.new_comment); // ... }}
Sunday, December 16, 12
findViewByIdpublic 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); // ... }}
is null at first...
Sunday, December 16, 12
findViewByIdpublic 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); // ... }}
initialized in method...
Sunday, December 16, 12
findViewByIdpublic class MyActivity extends Activity {
ListView comments; Button newComment;
@Override void onCreate(Bundle bundle) { super.onCreate(bundle); comments = (ListView) findViewById(R.id.comments); newComment = (Button) findViewById(R.id.new_comment); // ... }} Explicit casting!
Sunday, December 16, 12
Robo Guicepublic class MakeANoteActivity extends Activity 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;
// ... }
So many words...
Sunday, December 16, 12
Robo Guicepublic 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;
// ... }
Type changes in XML, but not here...
ClassCastException!
Sunday, December 16, 12
Robo Guicepublic 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;
// ... }
Guice is eager. Startup can take a few seconds!
Sunday, December 16, 12
Stairway to Scala
Sunday, December 16, 12
Another look at the Java codepublic class MakeANoteActivity extends RoboActivity implements View.OnClickListener
{ public static final String PHOTO_PATH = "picture_path"; public static final String PHOTO_ATTACHED = "photo_attached";
@Inject SessionManager sessionManager; @Inject LocationHelper locationHelper; @Inject PhotoHelper photoHelper; @Inject Application context;
@Inject CalibrationHelper calibrationHelper;
@InjectView(R.id.attach_photo) Button attachPhoto; @InjectView(R.id.note_text) EditText noteText; @InjectView(R.id.save_button) Button save; @InjectView(R.id.date) TextView dateText; @InjectView(R.id.share) Button share;
@InjectResource(R.string.im_aircasting) String imAircasting; @InjectResource(R.string.share_with) String shareWith;
// ... }
Sunday, December 16, 12
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;
// ... }
What if... Scala?
Sunday, December 16, 12
class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val imAircasting = findResource[String](R.string.im_aircasting) val shareWith = findResource[String](R.string.share_with)
def toastConferenceName() = "KrakDroid".toast()}
What if... Scala?
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
public is default.
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
ScalaActivity gives us some magic methods
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
ScalaActivity gives us some magic methods
It’s so easy, YOU can implement it!
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
ScalaActivity gives us some magic methods
It’s so easy, YOU can implement it!
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
Instead of “...Helper”,use Traits.
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
Type Inference
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
Who’s missing here?
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
lazy initialization
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
Needs Context
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
What’s the type here?!?
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
What’s the type here?!?
Typed Resource - “a better R”
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
What’s the type here?!?
Typed Resource - “a better R”
XML Type changes... Type here changes!
Sunday, December 16, 12
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: Button = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
What’s the type here?!?
Typed Resource - “a better R”
You can be explicit though!
Sunday, December 16, 12
class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
What if... Scala?
Like @InjectResource, but smarter
Manifests vs. Type Erasure
Sunday, December 16, 12
What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
Does String have a toast() method?
Implicit Conversion
Sunday, December 16, 12
Typed Resource
Sunday, December 16, 12
Typed Resource = Better R
Sunday, December 16, 12
Typed Resource = Better R
Sunday, December 16, 12
class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
Typed Resource = Better R
Sunday, December 16, 12
class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)
def toastConferenceName() = "KrakDroid".toast()}
Typed Resource
Typed Resource = Better R
Sunday, December 16, 12
case class TypedResource[T](id: Int)case class TypedLayout(id: Int)
object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager)
val workspaces = TypedResource[ExpandableListView](R.id.workspaces)
val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ...
}
Typed Resource = Better R
Sunday, December 16, 12
Typed Resource = Better R
case class TypedResource[T](id: Int)case class TypedLayout(id: Int)
object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager)
val workspaces = TypedResource[ExpandableListView](R.id.workspaces)
val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ...
}
Sunday, December 16, 12
Typed Resource = Better R
case class TypedResource[T](id: Int)case class TypedLayout(id: Int)
object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager)
val workspaces = TypedResource[ExpandableListView](R.id.workspaces)
val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ...
}
Wrappers
Sunday, December 16, 12
Typed Resource = Better R
case class TypedResource[T](id: Int)case class TypedLayout(id: Int)
object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager)
val workspaces = TypedResource[ExpandableListView](R.id.workspaces)
val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ...
}
Sunday, December 16, 12
Typed Resource = Better R
case class TypedResource[T](id: Int)case class TypedLayout(id: Int)
object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager)
val workspaces = TypedResource[ExpandableListView](R.id.workspaces)
val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ...
}
Sunday, December 16, 12
TR in Actionclass MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"
lazy val sessionManager = SessionManager.get // magic here but lazy val locationManager = LocationManager.get // we’ll see this later!
lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)
// magic here too, but we’ll implement this in a few slides! val imAircasting = findResource[String](R.string.im_aircasting) val shareWith = findResource[String](R.string.share_with)
// ...}
Sunday, December 16, 12
Types
Sunday, December 16, 12
Types
You always have the type information at hand.
Sunday, December 16, 12
Types
You always have the type information at hand.
(IntelliJ IDEA, Ensmine/Emacs, Eclipse)⌘ SHIFT I
ALT =
Sunday, December 16, 12
An Implicit Context
Sunday, December 16, 12
An Implicit Context
Implicit != Explicit
Sunday, December 16, 12
An Implicit ContextImplicit != Explicit
def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}
toastMyName(”Siegfried”, getContext)
Sunday, December 16, 12
def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}
toastMyName(”Siegfried”, getContext)
An Implicit ContextImplicit != Explicit
Explicit Parameter
Sunday, December 16, 12
def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}
toastMyName(”Siegfried”, getContext)
An Implicit ContextImplicit != Explicit
Explicit ParameterExplicit Parameter
Sunday, December 16, 12
def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}
toastMyName(”Siegfried”, getContext)
An Implicit ContextImplicit != Explicit
Import inside a method!
Sunday, December 16, 12
def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}
toastMyName(”Siegfried”, getContext)
An Implicit ContextImplicit != Explicit
Sunday, December 16, 12
def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}
An Implicit ContextImplicit != Explicit
Sunday, December 16, 12
Implicit ParametersImplicit != Explicit
def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}
Implicit Parameter
Sunday, December 16, 12
Implicit ParametersImplicit != Explicit
def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}
Sunday, December 16, 12
Implicit ParametersImplicit != Explicit
def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}
toastMyName("Siegfried")
Sunday, December 16, 12
Implicit ParametersImplicit != Explicit
def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}
implicit val context: Context = getContext
toastMyName("Siegfried")
Sunday, December 16, 12
Implicit ParametersImplicit != Explicit
def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}
implicit val context: Context = getContext
toastMyName("Siegfried")
toastMyName("Siegfried")(context)
Sunday, December 16, 12
An Implicit Context
class ScalaActivity extends Activity with ImplicitContext
Sunday, December 16, 12
An Implicit Context
trait ImplicitContext { this: Activity => implicit val ctx = getContext}
class ScalaActivity extends Activity with ImplicitContext
Sunday, December 16, 12
An Implicit Context
trait ImplicitContext { this: Activity => implicit val ctx = getContext}
class ScalaActivity extends Activity with ImplicitContext
“I can be only mixed intoan Activity.”
Sunday, December 16, 12
An Implicit Context
trait ImplicitContext { this: Activity => implicit val ctx = getContext}
class ScalaActivity extends Activity with ImplicitContext
“I can be only mixed intoan Activity.”
So I know this method!
Sunday, December 16, 12
Manifests vs. Type Erasure
Sunday, December 16, 12
Manifests vs. Type Erasure
Sunday, December 16, 12
List<Thing> t = marshaller.parseList("[]")
Manifests vs. Type Erasure
Java
Sunday, December 16, 12
List<Thing> t = marshaller.parseList("[]")
Manifests vs. Type Erasure
Java
Uhm... List<Object>...?
Sunday, December 16, 12
List<Thing> t = marshaller.parseList("[]")
List<Thing> t = marshaller.parseList("[]", Thing.class)
Manifests vs. Type Erasure
Java
Uhm... List<Object>...?
Sunday, December 16, 12
List<Thing> t = marshaller.parseList("[]")
List<Thing> t = marshaller.parseList("[]", Thing.class)
Manifests vs. Type Erasure
Java
Uhm... List<Object>...?
Oh! List<Thing>, sure!
Sunday, December 16, 12
List<Thing> t = marshaller.parseList("[]")
List<Thing> t = marshaller.parseList("[]", Thing.class)
val t: List[Thing] = marshaller.parseList("[]")
Manifests vs. Type Erasure
Java
Scala
Uhm... List<Object>...?
Oh! List<Thing>, sure!
Sunday, December 16, 12
List<Thing> t = marshaller.parseList("[]")
List<Thing> t = marshaller.parseList("[]", Thing.class)
val t: List[Thing] = marshaller.parseList("[]")
Manifests vs. Type Erasure
Java
Scala
Uhm... List<Object>...?
Oh! List<Thing>, sure!
List[Thing]!
Sunday, December 16, 12
val shareWith = findResource[String](R.string.share_with)
Manifests vs. Type Erasure
Sunday, December 16, 12
Manifests vs. Type Erasure
val shareWith = findResource[String](R.string.share_with)
Sunday, December 16, 12
Manifests vs. Type Erasure
val shareWith = findResource[String](R.string.share_with)
def findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T]
case other => throw new UnableToResolveResource(ofType = other, id = id) }
Sunday, December 16, 12
Manifests vs. Type Erasuredef findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T]
case other => throw new UnableToResolveResource(ofType = other, id = id) }
val shareWith = findResource[String](R.string.share_with)
implicit
Sunday, December 16, 12
Manifests vs. Type Erasuredef findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T]
case other => throw new UnableToResolveResource(ofType = other, id = id) }
val shareWith = findResource[String](R.string.share_with)
implicit Manifest
Sunday, December 16, 12
Manifests vs. Type Erasuredef findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T]
case other => throw new UnableToResolveResource(ofType = other, id = id) }
val shareWith = findResource[String](R.string.share_with)
the type signature
Sunday, December 16, 12
Manifests vs. Type Erasuredef findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] case "java.util.ArrayList[java.lang.String]" => newArrayList(ctx.getString(id).asInstanceOf[T])
case other => throw new UnableToResolveResource(ofType = other, id = id) }
val shareWith = findResource[String](R.string.share_with)
see the type... at runtime
Sunday, December 16, 12
Manifests vs. Type Erasuredef findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] case "java.util.ArrayList[java.lang.String]" => newArrayList(ctx.getString(id).asInstanceOf[T])
case "Int" => ctx.getString(id).toInt.asInstanceOf[T]
case other => throw new UnableToResolveResource(ofType = other, id = id) }
val shareWith = findResource[String](R.string.share_with)
Sunday, December 16, 12
Manifests vs. Type Erasuredef findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] case "java.util.ArrayList[java.lang.String]" => newArrayList(ctx.getString(id).asInstanceOf[T])
case "Int" => ctx.getString(id).toInt.asInstanceOf[T]
case other => throw new UnableToResolveResource(ofType = other, id = id) }
val shareWith = findResource[String](R.string.share_with)
java.lang.String has this...?
Sunday, December 16, 12
Implicit Conversions
Sunday, December 16, 12
Implicit Conversions
Implicit != Explicit
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
toastMyName("Siegfried")
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
toastMyName("Siegfried")
Implicit Context, remember?
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
toastMyName("Siegfried")
What if we could...
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
toastMyName("Siegfried")
"Siegfried".toast()
What if we could...
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
Decorator
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
DecoratorConstructor
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
new Toastable("Hello!").toast()
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
trait ScalaToasts {
implicit def asToastable(str: String) = new Toastable(str)}
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
trait ScalaToasts {
implicit def asToastable(str: String) = new Toastable(str)}
Implicit Conversion: String => Toastable
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
trait ScalaToasts {
implicit def asToastable(str: String) = new Toastable(str)}
asToastable("Hello!").toast()
Implicit Conversion: String => Toastable
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
trait ScalaToasts {
implicit def asToastable(str: String) = new Toastable(str)}
Implicit Conversion: String => Toastable
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
trait ScalaToasts {
implicit def asToastable(str: String) = new Toastable(str)}
class ExampleActivity extends Activity with ImplicitContext with ScalaToasts
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
trait ScalaToasts {
implicit def asToastable(str: String) = new Toastable(str)}
class ExampleActivity extends Activity with ImplicitContext with ScalaToasts
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
trait ScalaToasts {
implicit def asToastable(str: String) = new Toastable(str)} "Hello!".toast()
class ExampleActivity extends Activity with ImplicitContext with ScalaToasts
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
trait ScalaToasts {
implicit def asToastable(str: String) = new Toastable(str)} "Hello!".toast()
class ExampleActivity extends Activity with ImplicitContext with ScalaToasts
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
trait ScalaToasts {
implicit def asToastable(str: String) = new Toastable(str)} "Hello!".toast()
class ExampleActivity extends Activity with ImplicitContext with ScalaToasts
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
trait ScalaToasts {
implicit def asToastable(str: String) = new Toastable(str)} "Hello!".toast()
class ExampleActivity extends Activity with ImplicitContext with ScalaToasts
Sunday, December 16, 12
Implicit ConversionsImplicit != Explicit
class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}
trait ScalaToasts {
implicit def asToastable(str: String) = new Toastable(str)} "Hello!".toast()
class ExampleActivity extends Activity with ImplicitContext with ScalaToasts
asToastable("Hello!").toast()
Sunday, December 16, 12
Implicit Conversions
Sunday, December 16, 12
Collections
Sunday, December 16, 12
POJO
Sunday, December 16, 12
POJOpublic class Person { private final String name; private final String nick;
public Person(String name, String nick) { this.name = name; this.nick = nick; }
public String getName() { return name; }
public String getNick() { return nick; }
@Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Person)) return false;
Person person = (Person) o;
if (name != null ? !name.equals(person.name) : person.name != null) return false; if (nick != null ? !nick.equals(person.nick) : person.nick != null) return false;
return true; }
@Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (surname != null ? surname.hashCode() : 0); return result; }}
Sunday, December 16, 12
POJOpublic class Person { private final String name; private final String nick;
public Person(String name, String nick) { this.name = name; this.nick = nick; }
public String getName() { return name; }
public String getNick() { return nick; }
@Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Person)) return false;
Person person = (Person) o;
if (name != null ? !name.equals(person.name) : person.name != null) return false; if (nick != null ? !nick.equals(person.nick) : person.nick != null) return false;
return true; }
@Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (surname != null ? surname.hashCode() : 0); return result; }}
Sunday, December 16, 12
POSO**Actually just a Case Class
case class Person(name: String, nick: String)
Sunday, December 16, 12
case class Person(name: String, nick: String)
val name: String
POSO**Actually just a Case Class
Sunday, December 16, 12
case class Person(name: String, nick: String)
Case Classes
Sunday, December 16, 12
case class Person(name: String, nick: String)
Case Classes
Sunday, December 16, 12
case class Person(name: String, nick: String)
val person = Person("Bruce Wayne", "Manbat") // whoops!
Case Classes
Sunday, December 16, 12
case class Person(name: String, nick: String)
val person = Person("Bruce Wayne", "Manbat") // whoops!
Case Classes
val fixed = person.copy(nick = "Batman")
Sunday, December 16, 12
case class Person(name: String, nick: String)
val person = Person("Bruce Wayne", "Manbat") // whoops!
val self = Person(nick = "Ktoso" , name = "Konrad")
Case Classes
val fixed = person.copy(nick = "Batman")
Sunday, December 16, 12
case class Person(name: String, nick: String)
val person = Person("Bruce Wayne", "Manbat") // whoops!
val self = Person(nick = "Ktoso" , name = "Konrad")
val Person(name, hero) = personval hello = ”Hello” + name + ” ” + surname
Case Classes
val fixed = person.copy(nick = "Batman")
Sunday, December 16, 12
case class Person(name: String, nick: String)
val person = Person("Bruce Wayne", "Manbat") // whoops!
val self = Person(nick = "Ktoso" , name = "Konrad")
val Person(name, hero) = personval hello = ”Hello” + name + ” ” + surname
fixed.toString should equal (”Person(Bruce Wayne, Batman)”)
Case Classes
Still thinking assertThat().isEqualTo() is clean?
val fixed = person.copy(nick = "Batman")
Sunday, December 16, 12
Given a list of People,return all the Hero names.
Sunday, December 16, 12
public List<String> heroNames(List<Person> allPersons) { List<String> donePersons = new ArrayList<String>(allPersons.size());
for (Person person : allPersons) { if (person.isHero()) { donePersons.add(person.getName()); } }
return ImmutableList.copyOf(donePersons); }
Given a list of People,return all the Hero names.
Sunday, December 16, 12
Java with Guava at their BestGiven a list of People,
return all the Hero names.
Sunday, December 16, 12
Java with Guava at their Best
return FluentIterable .from(people) .filter(new Predicate<Person>() { @Override public boolean apply(Person person) { return person != null && person.isHero(); } }) .transform(new Function<Person, String>() { @Override public String apply(Person input) { return input.getName(); } }) .toImmutableList();
Given a list of People,return all the Hero names.
Sunday, December 16, 12
Sunday, December 16, 12
Java + Guava at their bestGiven a list of People,
return all the Hero names.
Sunday, December 16, 12
Java + Guava at their best
return FluentIterable .from(people) .filter(isSuperHero) .transform(heroToName) .toImmutableList();
Java, yet pretty slick :-)I <3 Guava.
Given a list of People,return all the Hero names.
Sunday, December 16, 12
Scala Collections at WorkGiven a list of People,
return all the Hero names.
Sunday, December 16, 12
def heroNames(people: List[Person]) = people filter(_.isHero) map { _.name}
Scala Collections at WorkGiven a list of People,
return all the Hero names.
Sunday, December 16, 12
And there’s more!
Sunday, December 16, 12
Simple Threading
Sunday, December 16, 12
Simple Threading
implicit val handler = new Handler
Sunday, December 16, 12
Simple Threading
implicit val handler = new Handler
inUiThread { // ...}
Sunday, December 16, 12
Simple Threading
implicit val handler = new Handler
inFutureWithProgressDialog(timeout = 10.seconds) { // ...}
inUiThread { // ...}
Sunday, December 16, 12
Simple Threading
implicit val handler = new Handler
inFutureWithProgressDialog(timeout = 10.seconds) { // ...}
inUiThread { // ...}
Implicit Conversion on Int
Sunday, December 16, 12
on___
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // ... }});
Java
Sunday, December 16, 12
on___
button onClick { view => // ...}
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // ... }});
Java
Scala
Sunday, December 16, 12
SharedPreferences
Sunday, December 16, 12
SharedPreferences
KanbaneryPreferences.projectId = projectId
Sunday, December 16, 12
SharedPreferences
KanbaneryPreferences.projectId = projectId
val name: Option[Long] = KanbaneryPreferences.projectId
Sunday, December 16, 12
SharedPreferences
KanbaneryPreferences.projectId = projectId
val name: Option[Long] = KanbaneryPreferences.projectId
What? No implicits?! Assume it works! Skip!
Sunday, December 16, 12
SharedPreferencesobject KanbaneryPreferences {
private val KeyLogin = "login"
private def sharedPreferences(implicit ctx: Context) = ???
def login(implicit ctx: Context) = sharedPreferences.getString(KeyLogin, "")
Sunday, December 16, 12
SharedPreferencesobject KanbaneryPreferences {
private val KeyLogin = "login"
private def sharedPreferences(implicit ctx: Context) = ???
def login(implicit ctx: Context) = sharedPreferences.getString(KeyLogin, "")
Sunday, December 16, 12
SharedPreferencesobject KanbaneryPreferences {
private val KeyLogin = "login"
private def sharedPreferences(implicit ctx: Context) = ???
def login_=(number: String)(implicit ctx: Context) { withSharedPreferencesEditor { _.putString(KeyLogin, number) }
}
Sunday, December 16, 12
SharedPreferencesobject KanbaneryPreferences {
private val KeyLogin = "login"
private def sharedPreferences(implicit ctx: Context) = ???
def login_=(number: String)(implicit ctx: Context) { withSharedPreferencesEditor { _.putString(KeyLogin, number) }
}
Sunday, December 16, 12
SharedPreferences
def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) {
val editor = sharedPreferences.edit()
block(editor)
editor.commit()}
Sunday, December 16, 12
SharedPreferences
def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) {
val editor = sharedPreferences.edit()
block(editor)
editor.commit()}
Sunday, December 16, 12
SharedPreferences
def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) {
val editor = sharedPreferences.edit()
block(editor)
editor.commit()}
Sunday, December 16, 12
SharedPreferences
def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) {
val editor = sharedPreferences.edit()
block(editor)
editor.commit()}
withSharedPreferencesEditor { _.putString(KeyLogin, number) }
Sunday, December 16, 12
String interpolation(scala 2.10)
Sunday, December 16, 12
String interpolation(scala 2.10)
Sunday, December 16, 12
String interpolation(scala 2.10)
Sunday, December 16, 12
String interpolation(scala 2.10)
Won’t compile!
Sunday, December 16, 12
Let me warn you...
Sunday, December 16, 12
Let me warn you...
Scala is addictive.
Sunday, December 16, 12
Let me warn you...
Scala is addictive.
Sunday, December 16, 12
Scala is addictive.
Sunday, December 16, 12
Scala is addictive.
Sunday, December 16, 12
Scala is addictive.
Sunday, December 16, 12
Scala is addictive.
Sunday, December 16, 12
def links = • Scala Lang http://www.scala-lang.org/
• Scala Koans http://www.scalakoans.org
• Blog.Project13.pl - http://www.blog.project13.pl
• SBT Android Plugin - https://github.com/jberkel/android-plugin
• Kanbanery for Android - https://github.com/ktoso/kanbanery-tv• Check pl.project13.scala.android.*• Now OpenSource, in Scala, and Lunar Logic is helping to dev :-)• New version soon! Pull and play with it!
• Scaloid https://github.com/pocorall/scaloid• Though I don’t think their impl. is very clean some things are v. nice!
Sunday, December 16, 12
def links = • Scala Lang http://www.scala-lang.org/
• Scala Koans http://www.scalakoans.org
• Blog.Project13.pl - http://www.blog.project13.pl
• SBT Android Plugin - https://github.com/jberkel/android-plugin
• Kanbanery for Android - https://github.com/ktoso/kanbanery-tv• Check pl.project13.scala.android.*• Now OpenSource, in Scala, and Lunar Logic is helping to dev :-)• New version soon! Pull and play with it!
• Scaloid https://github.com/pocorall/scaloid• Though I don’t think their impl. is very clean some things are v. nice!
Mailing lists rock!
Sunday, December 16, 12
Konrad Malawski / @ktosoplGDG / PJUG / KSUG / SCKRK
KrakDroid 14.12.2012Sunday, December 16, 12
Konrad Malawski / @ktosoplGDG / PJUG / KSUG / SCKRK
KrakDroid 14.12.2012
I love feedback! <3
Sunday, December 16, 12