34
Scaladroids Ostap Andrusiv

Scaladroids: Developing Android Apps with Scala

Embed Size (px)

DESCRIPTION

Android is a fast-growing mobile operating system with millions of users worldwide. Scala is a modern programming language designed to express common programming patterns in a concise, elegant, and type-safe way. Why not combine both of them?

Citation preview

Page 1: Scaladroids: Developing Android Apps with Scala

ScaladroidsOstap Andrusiv

Page 2: Scaladroids: Developing Android Apps with Scala

About me

Page 3: Scaladroids: Developing Android Apps with Scala

Agenda

What is android? What is scala?

Scala your android?

Page 4: Scaladroids: Developing Android Apps with Scala

Why Scala?Why Scala?

Page 5: Scaladroids: Developing Android Apps with Scala

Scala

Concise

Type-safe

Functional && OO

Page 6: Scaladroids: Developing Android Apps with Scala

RSSReader

~400

~150LOC

Page 7: Scaladroids: Developing Android Apps with Scala

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

Page 8: Scaladroids: Developing Android Apps with Scala

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

Page 9: Scaladroids: Developing Android Apps with Scala

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 !!!

Page 10: Scaladroids: Developing Android Apps with Scala

1

Page 11: Scaladroids: Developing Android Apps with Scala

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() = ... }

Page 12: Scaladroids: Developing Android Apps with Scala

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}

Page 13: Scaladroids: Developing Android Apps with Scala

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._

Page 14: Scaladroids: Developing Android Apps with Scala

Scaladroiding...

* -- S for Scala

Page 15: Scaladroids: Developing Android Apps with 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; }}

Page 16: Scaladroids: Developing Android Apps with Scala

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)

Page 17: Scaladroids: Developing Android Apps with Scala

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)

Page 18: Scaladroids: Developing Android Apps with Scala

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 :( ?

Page 19: Scaladroids: Developing Android Apps with Scala

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?

Page 20: Scaladroids: Developing Android Apps with Scala

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...

Page 21: Scaladroids: Developing Android Apps with Scala

"Pimp My Library" Ninja!

Page 22: Scaladroids: Developing Android Apps with Scala

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?

Page 23: Scaladroids: Developing Android Apps with Scala

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?

Page 24: Scaladroids: Developing Android Apps with Scala

// ... 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

Page 25: Scaladroids: Developing Android Apps with Scala

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

Page 26: Scaladroids: Developing Android Apps with Scala

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

Page 27: Scaladroids: Developing Android Apps with Scala

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}

Page 28: Scaladroids: Developing Android Apps with Scala

Async Tasks

// ... in Javish Scala:new AsyncTask[String, Void, Object] { override def doInBackground(params: String*) : Object = { // download data }}.execute()

Page 29: Scaladroids: Developing Android Apps with Scala

Async Tasks

// ... in Scala:async { // download data

}

// same applies to Handlers, post, threads, etc.

Page 30: Scaladroids: Developing Android Apps with Scala

Scala Issues on Android

Maps API wrapper or

v2 API

Solutions:

ProGuard

Page 31: Scaladroids: Developing Android Apps with Scala

Magic behind

Page 32: Scaladroids: Developing Android Apps with Scala

Magic behind

Page 33: Scaladroids: Developing Android Apps with Scala