Android &Functional ProgrammingFor Great Good™ – Abstraction – A cartographic case



Android &Functional ProgrammingFor Great Good™ – Abstraction – A cartographic case

0 0


codebits2014

My talk “Android and functional programming for Great Good™” at Codebits 2014

On Github stanch / codebits2014

Android &Functional ProgrammingFor Great Good™

Nick @stanchmehttp://github.com/stanch

What is Android?

A kind of candy?

What is functional programming?

Composability

Abstraction

Abstraction

Now it makes sense

“Plumbing’s just Lego, innit? Water Lego...”

— Superhans, Peep Show

Tools of the trade

Scala [+]

  • Compiles to Java Bytecode
  • Object-Oriented + Functional

Who uses Scala?

Values

val x = 4

Values

val x: Int = 4

Methods

def add(x: Int, y: Int) = x + y

Methods

def add(x: Int, y: Int): Int = {
  x + y
}

Anonymous functions

(x: Int) ⇒ x + 3

Anonymous functions

x ⇒ x + 3

Anonymous functions

_ + 3

Syntax-bending

5.add(5) ⇔ 5 add 5
bird.♫("lala") ⇔ bird ♫ "lala"
say("Hi!") ⇔ say { "Hi!" }

Let’s see it in action!

A cartographic case

A cartographic case

Given a list of cities,

select those with a river,

take top-5 of

the most populated ones, and

put each of them on the map.

Code poetry? [+]

cities
  .filter(_.hasRiver)
  .sortBy(-_.population)
  .take(5)
  .foreach { c ⇒
    addToMap(c.name, c.coordinates)
  }

Not too early!

Declare a property you need,

but do not call any APIs

before the UI is ready

Some laziness helps

lazy val title =
  getArguments.getString("title")

What about all those nulls?

Code haiku! [+]

lazy val title =
  Option(getArguments)
  .flatMap(a ⇒ Option(a.getString("title")))
  .getOrElse("Hello")

Get off my lawn!

Run a difficult computation

outside the main thread

and do something with the result

when it’s ready.

The future [+]

val result = Future {
  val x = longComputation(41.5)
  x + 5
}
result onComplete {
  case Success(x) ⇒ doSomething(x)
  case Failure(t) ⇒ handle(t)
}

What is a future?

many seconds ⇒ 42

“Don’t put off until tomorrow what you can do today”

— Benjamin Franklin

Operating in the future

many seconds ⇒ 42 ↓ many seconds ⇒ 43

Operating in the future [+]

val fortyTwo = Future { ... }

val fortyThree = fortyTwo.map(_ + 1)

fortyThree onComplete { ... }

Async orchestration

get from database ⇒ $30 * ask google ⇒ 0.72 €/$ ↓ a few seconds later ⇒ €21.6

Async orchestration [+]

val euros = async {
  val future1 = getDollarsFromDb
  val future2 = googleConversionRate
  val d = await(future1)
  val r = await(future2)
  d * r
}

Wait, what about GUI?

Android XML layouts

  • Verbose
  • XML + code boilerplate
  • Only one per file
  • No namespacing

Macroid [+]

Experimental modular functional UI language for Android, written in Scala.

Bricks

w[Button]

Bricks

l[LinearLayout](
  w[Button],
  w[TextView]
)

Bricks

val brick1 = w[Button]
val brick2 = w[TextView]

l[LinearLayout](
  brick1, brick2
)

Tweaking

w[TextView] <~ text("Hello")

Tweaking

def largeText(str: String) =
  text(str) +
  TextSize.large +
  padding(left = 8 dp)

w[TextView] <~ largeText("Hello")

A complete example

var greeting = slot[TextView]

l[LinearLayout](
  w[Button] <~
    text("Greet me!") <~
    On.click {
      greeting <~ show
    },

  w[TextView] <~
    text("Hello there") <~
    wire(greeting) <~ hide 
)

What about adaptivity?

The Android way

  • A folder per screen size
  • Limited layout reuse

Media queries

val textStyle =
  widerThan(400 dp) ?
  TextSize.large |
  TextSize.medium

w[TextView] <~ textStyle

New ways of expression

? <~ ?

Optional tweaking

onlySeenInHD <~ (hdpi ? show)

Batch tweaking

List(textView1, textView2) <~ hide

Tweaking from the future

many seconds ⇒ "Hello" ↓ many seconds ⇒ text("Hello")

Tweaking from the future

val futureCaption = Future {
  Thread.sleep(5000)
  text("Hello")
}

myTextView <~ futureCaption

And now for something completely different...

Starting procedures

Install SBT (build tool) Install Intellij IDEA (or Android Studio) Add Scala and SBT plugins to IDEA Add Android and IDEA plugins to SBT Write a build file Generate IDE project files Run! -or- In utter rage, post in the Mailing list

The build file

name := "Project-name"

version := "1.0"

platformTarget in Android := "android-19"

libraryDependencies ++= Seq(
  "com.loopj.android" % "android-async-http" % "1.4.4",
  "com.android.support" % "support-v13" % "19.1.0",
  aar("com.google.android.gms" % "play-services" % "4.0.30")
)

Connecting the IDE

sbt
> gen-idea

(live IDE demo)

Some flies in the ointment

Scala library is around 5 MB

Squeeze it with ProGuard

Build time goes up to 1 min / 10K LOC;

ProGuard config takes some effort

Learn more

This presentation: http://stanch.github.io/codebits2014