scaladroids: developing android apps with scala

Post on 28-Jan-2015

114 Views

Category:

Technology

4 Downloads

Preview:

Click to see full reader

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?

TRANSCRIPT

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

top related