android development with scala and sbt

Post on 12-Apr-2017

116 Views

Category:

Engineering

5 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Android Development with Scala and SBT

--Anton YalyshevJetBrains

AnDevCon | Contents

Contents:

1. Build tool: SBT

2. Scala for Android development

3. Simple application

4. 3rd party libraries

AnDevCon | Scala Build Tool

// Project’s namename := "my-project"

version := "1.0.0"

// Add dependencieslibraryDependencies ++= Seq( "net.databinder" %% "dispatch-google" % "0.7.8", "net.databinder" %% "dispatch-meetup" % "0.7.8")

// Add dependency for testslibraryDependencies += "junit" % "junit" % "4.8" % "test"

// Define a repository by project’s version publishTo := Some(if (version.value endsWith "-SNAPSHOT") "http://example.com/maven/snapshots" else "http://example.com/maven/releases")

AnDevCon | Scala Build Tool > Features

Distinctive features

● Runs in Command line

● More support in Scala ecosystem

● Convenient cross-compilation and cross-publishing

● Fast tasks execution

● Everything is a task with return value

AnDevCon | Scala Build Tool Common tasks

Command Description

android:run Compile, package a debug apk and deploy it to an active device

android:packageRelease Create a signed apk

android:packageDebug Create a debug apk

test Run unit tests and report results

reload Apply changes that have been made to your sbt configuration

compile Compile the source code

clean Remove all compiled and generated code, delete ProGuard cache.

AnDevCon | Scala for Android development

Benefits:● Null is replaced by Option type● Lazy values for declaration and processing● 3rd party libraries● Resolve concurrency problems

Prior information:● 65K global method limit● Tools versions compatibility

AnDevCon | Scala for Android development > Option type

Option [ T ]

Some [ T ] None

case class User( firstName: String, lastName: String, phone: Option[String])

val user = User("John", "Doe", None)println("Phone: " + user.phone.getOrElse("not specified"))

AnDevCon | Scala for Android development > Lazy values

Keyword Data type № of evaluations When?

val Immutable data Only once At the time of definition

Lazy val Immutable data Only once When we access it for first time

var Mutable data Only once At the time of definition

def Methods and Functions Every-time we access it When we access it

AnDevCon | Scala for Android development > Lazy values

class AndroidWay extends Activity { TextView name; ImageView thumbnail;

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); name = (TextView) findViewById(R.id.name); thumbnail = (ImageView) findViewById(R.id.thumbnail); }}

class ButterKnifeWay extends Activity { @BindView(R.id.title) TextView title; @BindView(R.id.thumbnail) ImageView thumbnail;

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_activity); ButterKnife.bind(this); // ... }}

class ScaloidWay extends SActivity {

lazy val name = findView(TR.id.name) lazy val thumbnail = new ImageView()

onCreate { contentView = new SVerticalLayout { name.here thumbnail.here } }}

AnDevCon | Scala for Android development > TR

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android">

<TextView android:id="@+id/my_title" android:layout_width="wrap_content" android:layout_height="wrap_content" />

</LinearLayout>

public class MyActivity extends Activity { @Override protected void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState );

setContentView( R.layout.view );

TextView title = (TextView) findViewById( R.id.my_title ); title.setText( "Hello Java!" ); }}

class MyActivity extends Activity { override def onCreate( savedInstanceState: Bundle ) = { super.onCreate( savedInstanceState )

setContentView( R.layout.main )

val title = findViewById( R.id.my_title ).asInstanceOf[TextView] title.setText( "Hello Scala!" ) }}

class MyActivity extends Activity with TypedActivity { override def onCreate( savedInstanceState: Bundle ) = { super.onCreate( savedInstanceState )

setContentView( R.layout.main )

val title = findView( TR.my_title ) title.setText( "Hello Scala!" ) }}

AnDevCon | Scala for Android development > Concurrency management

Concurrency problems are resolved by

○ Futures

○ scala-async

○ Akka. UI Fragments -> actors

○ resolvable: to fill data structure from different endpoints

AnDevCon | Scala for Android > Concurrency > Futures

new AsyncTask[String, Void, String] { def doInBackground(params: Array[String]) = { doAJobTakeSomeTime(params) }

override def onPostExecute(result: String) { alert("Done!", result) }}.execute("param")

Future { val result = doAJobTakeSomeTime(params) runOnUiThread(alert("Done!", result))}

val future = async { val f1 = async { … ; true } val f2 = async { … ; 42 } if (await(f1)) await(f2) else 0}

AnDevCon | Scala for Android > Concurrency > Actor model

Actor

UI Fragment 2

Actor

UI Fragment 1

Actor

UI Fragment 3

Actor

UI Fragment 4

AnDevCon | Scala for Android development >

Frequent questions:

● 65K global method limit ⇒ ProGuard

● Tools versions compatibility

○ Target bytecode version: 1.7

○ Android build tools <= 23.*

AnDevCon | Steps to create simple application

IDE →

AnDevCon | 3rd party libraries > Scaloid > Overview

Benefits:● Easy to use● Compatible with legacy Java code● Production quality

Principles:● Simplicity; ● Programmability;● Type-safety.

AnDevCon | 3rd party libraries > Scaloid > Short and easy code

val button = new Button(context)button.setText("Greet")button.setOnClickListener(new OnClickListener() { def onClick(v: View) { Toast.makeText(context, "Hello!", Toast.LENGTH_SHORT).show() }})layout.addView(button)

SButton("Greet", toast("Hello!"))

AnDevCon | 3rd party libraries > Scaloid > Short and easy code

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="wrap_content" android:padding="200dip"><TextView android:layout_width="match_parent" android:text="ID" android:id="@+id/userid"

android:layout_height="wrap_content" /><EditText android:layout_width="match_parent" android:layout_height="wrap_content"

android:id="@+id/userid" /><Button android:layout_width="match_parent" android:text="Sign in" android:id="@+id/signin"

android:layout_height="wrap_content"/></LinearLayout>

EditText userId = (EditText) findByViewId(R.id.userid);Button signin = (Button) findByViewId(R.id.signin);signin.setOnClickListener(new View.OnClickListener() { public void onClick (View v) { signin(userId.getText()) }}); new SVerticalLayout {

STextView("ID") val userId = SEditText() SButton("Sign in", signin(userId.text))}.padding(20dip)

AnDevCon | 3rd party libraries > Scaloid > Short and easy code

broadcastReceiver(ConnectivityManager.CONNECTIVITY_ACTION) { doSomething()}(this, onStartStop)

Future { alert("Done!", doAJobTakeSomeTime(params))}

AnDevCon | 3rd party libraries > Macroid

Macroid: motivation● XML approach limitations

● Inconvenient namespace system

● Potential risk of NPE

● Adaptation of Scala language features

AnDevCon | 3rd party libraries > Macroid > Components

Button:

new Button(ctx) w[Button]

Layout:

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

Properties: w[Button] <~ text("Hello!") <~ TextTweaks.large

AnDevCon | 3rd party libraries > Macroid > Tweaking

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

w[Button] <~ largeText("...")

Tweaks composition ? <~ ?

ButtonList [ Button ]

Tweak [ Button ]List [ Tweak [ Button ]

Option [ Button ],...

Option [ Tweak [ Button ]Future [ Tweak [ Button ]

val caption: Future[String] = Future { ...}

myTextView <~ caption.map(text)

AnDevCon | 3rd party libraries > Macroid > Snails

Fade-in Text: ”Click me!”

Snails

mybutton <~~ fadeIn(400) <~ text("Click me!") <~~ fadeOut(400)

await

val blink = fadeIn(400) ++ delay(2000) ++ fadeOut(400)

myTextView <~~ blink

await

AnDevCon | 3rd party libraries > Macroid > UI Actions

val action = myTextView <~ text(“Hi!”) <~ show...action.run// orrunUi(action)

val action1 = myTextView <~ text(“Hi!”) <~ show

val action2 = myProgressBar <~ hide ...runUi(action1 ~ action2)

runUi { (myProgressBar <~~ fadeOut(400)) ~~ (myTextView <~~ blink) ~~ (myOtherVextView <~ text("Hi!"))}

AnDevCon | 3rd party libraries > Macroid > Operators

Right now Await

Apply <~ <~~

Combine + ++

UI Actions seq. ~ ~~

AnDevCon | 3rd party libraries > Macroid > Other features

● Scala’s implicit parameters system

● Pattern matching mechanism ● Macroid lib. Media query system

● Macroid Bricks system

● Scala types system● Contexts management● Adaptive Layout● Simple work work Fragments● Data sources adapter

AnDevCon | 3rd party libraries > Macroid > Akka

Actor

UI Fragment 1

Actor

UI Fragment 1

Actor

UI Fragment 1

Actor

UI Fragment 1

libraryDependencies ++= Seq(

// this library

aar("org.macroid" %% "macroid-akka" % "2.0.0-M4"),

// akka, if not included before

"com.typesafe.akka" %% "akka-actor" % "2.3.9"

)

AnDevCon | Summary

1. SBT as de-facto build tool for Scala projects

2. Scala language features help us in

- risks of NPE

- values calculation control

- concurrency problems

3. 3rd party libraries

- type-safety

- simplification in work with platform

top related