Scaladroids: Developing Android Apps with Scala
-
Upload
ostap-andrusiv -
Category
Technology
-
view
117 -
download
4
description
Transcript of Scaladroids: Developing Android Apps with Scala
ScaladroidsOstap Andrusiv
About me
Agenda
What is android? What is scala?
Scala your android?
Why Scala?Why Scala?
Scala
Concise
Type-safe
Functional && OO
RSSReader
~400
~150LOC
Expressions & Values
pif@pif:~/ $ scala
scala> 20 + 22res1: Int = 42
scala> val fourtyTwo = 100 - 58fourtyTwo: Int = 42
scala> fourtyTwo = -1<console>:8: error: reassignment to val
scala> var number = 42number: Int = 42
scala> number = -1number: Int = -1
Functions
pif@pif:~/ $ scala
scala> def add42(a: Int) = | a + 42add42: (a: Int)Int
scala> add42(50 + 5*5*2)res0: Int = 142
scala> def minusOne() = | -1minusOne: ()Int
scala> 43 + minusOneres1: Int = 42
Java Classpublic class RSSEntry { private String name; private String description; private String link;
public RSSEntry(String name, String description, String link) { super(); this.name = name; this.description = description; this.link = link; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
// ... 50 LINES more !!!
1
Scala class
class RSSEntry(name: String, description: String, link: String) {}// that's it! Nothing more!
case class RSSEntry(name: String, description: String, link: String)// class + equals(), hashCode() & lots of other useful stuff
object RSSEntry { def customize() = ... }
Basic Inheritance & Traits
class RSSEntry(name: String, desc: String) {}// that's it! Nothing more!
class AuthoredRSSEntry(name: String, desc: String, author: String) extends RSSEntry(name, desc) {}
trait HtlmView { def asHTLMString() : String}trait PlainView { def asPlainText() : String}
class NiceRSSEntry(name: String, desc: String) extends RSSEntry(name, desc) with HtmlView with PlainView { // ... asHTLMString & asPlainText}
Collections FTW!
Task: From all #ADD tweets, find those programmers, who know .NET and give them Coockies!!!
Java: // ~50 lines of mess and pain in the ass...
Scala: tweets .filter (_ contains "#ADD13") .flatMap(_ split " " ) .filter (_ startsWith "@" ) .map (t => person(t)) .filter (_ langs contains (".net")) .foreach(giveCookies _)
//import scala.collection.JavaConverters._
Scaladroiding...
* -- S for Scala
Layout
<LinearLayout xmlns:android="http://schemas.android.com/ap... k/res/android" android:layout_width... >
<TextView android:id="@+id/text_name" android:textSize... />
<TextView android:id="@+id/text_descr" android:textSize... /></LinearLayout>
// ... in R.java:public final class R { // ... public static final class id { // ... public static final int text_descr=0x7f090003; public static final int text_name=0x7f090002; }}
Layout Usage
// ... in Java:TextView itemName = (TextView) findViewById(R.id.text_name);TextView itemDesc = (TextView) findViewById(R.id.text_descr);
itemName.setText(item.getShortName());itemDesc.setText(item.getShortDescription());
// ... in Scala:val itemName = findViewById(R.id.text_name).asInstanceOf[TextView]val itemDesc = findViewById(R.id.text_descr).asInstanceOf[TextView]
itemName.setText(item.getShortName)itemDesc.setText(item.getShortDescription)
TypedResource TR.scala
object TR { val itemName = TypedResource[android.widget.Button](R.id.text_name) // ...}
// ==> ... in Scala:
val itemName = findViewById(R.id.text_name).asInstanceOf[TextView]val itemDesc = findViewById(R.id.text_descr).asInstanceOf[TextView]
val itemName = findView(TR.itemName)val itemDesc = findView(TR.itemDesc)
Event Handlers & Listeners// ... in Java:Button b = (Button) findViewById(R.id.action_check);b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // ... make user happy :) }});
// ... in Scala:val b = findView(TR.buttonCheck)b setOnClickListener(new View.OnClickListener { override def onClick(v: View) { // ... make user happy :) }})
// hmmm... no benefit from this :( ?
Event Handlers & Listeners// ... in Scala:val b = findView(TR.buttonCheck)b setOnClickListener(new View.OnClickListener { override def onClick(v: View) { // ... make user happy :) }})
// hmmm... no benefit from this :( ?// this is java-like scala! Rewrite it:
b onClick { /* make user happy */ }
// b has no onClick method!!! Where is it from?
Implicits
// ... in Scala:class ShortString(s: String) { def short = if (s.length > 10) s.substring(0,7) + “...” else s}
new ShortString(“Very very long greeting”).short// Very ve...
implicit def string2Shortstr(s: String) = new ShortString(s)
“Very very long greeting”.short// Very ve...
"Pimp My Library" Ninja!
Implicits
// ... in Scala:class ClickableView(v: View) { def onClick(u: Unit) { v.setOnClickListener(new View.OnClickListener() { override def onClick(v: View) = u }) } }
implicit def view2ClickView(v: View) = new ClickableView(v)
// ... later in Scala:b onClick { “make user happy”.toast }
// oh... implicit ..toasts?
Implicits
// ... in Java:Toast.makeText(ctx, "Toast!", Toast.LENGTH_LONG).show();
// ... in Scala:class ToastableString(s: String) { def toast(ctx: Context) = Toast.makeText(ctx, s, Toast.LENGTH_LONG).show}
// ... later in Scala:“make user happy”.toast(getApplicationContext)
// find 1 difference:“make user happy”.toast
// wtf? Where can we get context?
// ... magic is in Scala:trait Toasty { class ToastString(s: String) { def toast(implicit ctx: Context) = Toast.makeText(ctx, s, Toast.LENGTH_LONG).show }
implicit def string2ToastString(s: String) = new ToastString(s)}
class NiceActivity extends Activity with Toasty { implicit val ctx = getApplicationContext “make users happy”.toast}
Implicits
Shared Preferences
// ... in Java:SharedPreferences.Editor sp = ctx.getSharedPreferences(KEY, 0).edit();editor.putString("hello", "world");editor.commit();
// ... in Scala:AppSharedPrefs.hello = "Julia"(AppSharedPrefs.hello + ", you look awesome!").toast
Menus// ... in Java:@Overridepublic boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.entries, menu); return true;}
// ... in Scala:trait Menus { override def onCreateOptionsMenu(menu: Menu) = { getMenuInflater.inflate(R.menu.entries, menu) true }}
class EntriesActivity extends ListActivity with Menus
Closable// ... in Java:try { // do some tricky work...finally { tricky.close();}
// ... in Scala:trait Closers { def closeAfter[A <: {def close():Unit}, B](param:A)(f: A => B):B = { try { f(param) } finally { param.close } } }
// work with DB cursors:closeAfter(db.query(...params...)) { cu => // analyze cursor data}
Async Tasks
// ... in Javish Scala:new AsyncTask[String, Void, Object] { override def doInBackground(params: String*) : Object = { // download data }}.execute()
Async Tasks
// ... in Scala:async { // download data
}
// same applies to Handlers, post, threads, etc.
Scala Issues on Android
Maps API wrapper or
v2 API
Solutions:
ProGuard
Magic behind
Magic behind
Let the Scala be with you!
?*Thanks!
CourseraTwitter Scala SchoolTwitter Effective ScalaOdersky Bookstackoverflow