REPL your way into Android development

by @doppioslash

12 Semptember 2015 - FunctionalKats - Dublin

So you want to make
Android apps

but not to use Java

and/or want a better way to develop Android UI

The Horror of XML

Luckily for you there are many languages you can use

Scala

Kotlin

But today we're looking at

Clojure

Interactive

Concise

(At least compared to Java. The bar is low.)

Good Interop

Watch out for

Android SDK install downloading  the internet

Android

Android

Having to tap 7 times to get developer access.

 

(And jump counterclockwise on one foot on a full moon night)

Android

Or you can ask your cat to tap for you

Loading times

Clojure

Clojure

Solution: skummet

Still need Android proficiency

Clojure

No solution to that...

Need Android proficiency

Need Android proficiency

We can save you from XML but NOT from Android Layouts

Let me present you your new friends

[lein-droid "0.4.3"]

lein droid

A lein plugin

lein droid

Creates project

lein droid

Compiles

lein droid

Runs on device

[neko/neko "4.0.0-alpha5"]

neko

Wraps the Android API

neko

Activity

neko

Interactively develop UIs

neko

With no XML

neko

Logging

neko

Action Bars

neko

SQLite

[org.skummet/clojure "1.7.0-r1"]

skummet

Fork of Clojure

skummet

Faster boot times

skummet

More compact

skummet

Skips unused

[cider/cider-nrepl "0.9.1"]

cider

Emacs IDE and REPL

cider

M-x cider-connect

cider

cider

Will give you a REPL that runs on device

Setup

Setup

1. Create a new project with lein droid

Setup

$ lein new droid <project>

<package> <opts> 

Setup

$ lein new droid anfocal

com.lambdacat.anfocal :sdk-target 23

Setup

Will automatically install the lein droid template

Setup

Tree of lein-droid app 

Setup

2. Open your project.clj in Emacs

Setup

3. Specify path to Android SDK in project.clj

Setup

:sdk-path "/usr/local/opt/android-sdk"

Setup

4. Launch emulator or plug in device

Setup

(pss, the Android emulator is slow. Try Genymotion)

Setup

4. open a shell in Emacs

Setup

M-x shell

M-x shell

6. compile and launch the project

M-x shell

$ lein droid doall

M-x shell

Will compile and launch in your emulator

Setup

7. get a REPL connected with the clojure on device

Setup

M-x cider-connect

Setup

localhost:9999

M-x cider-connect

Opens REPL on device

M-x cider-connect

8. We can change the code and

C-x C-e to re-evaluate

M-x cider-connect

Setup

Demo

Android Overview

Android Overview

Activity

Activity

is a single screen

Activity

should equate to one action the user can take

Activity

eg. Login -> LoginActivity

Android Overview

Fragment

Android Overview

is a piece of UI you can use in an Activity

Android Overview

one Activity can have many Fragments

Android Overview

Intent

Android Overview

is an async message

Android Overview

that contains the data needed to do an action

Android Overview

an app/activity can offer/support an intent

Intent

eg. app: I can open a pdf

Intent

meaning it has some functionality

Intent

connects different screen in an app

Intent

but can also connect different apps

Intent

ActionBar

Intent

a way to do navigation

Intent

can show contextual buttons

neko

neko

An idiomatic wrapper to Android APIs

neko

defactivity

neko - defactivity

Is a macro

neko - defactivity

Assign unique key with :key

main.clj

You can find it again much like CSS selectors

main.clj

find-view

main.clj

main.clj

Where our main Activity resides

main.clj

... [neko.activity :refer [defactivity set-content-view!]])

 

(defactivity   com.lambdacat.anfocal.AnFocalActivity
  :key :main

  (onCreate [this bundle]
    (.superOnCreate this bundle)
    (on-ui ...

main.clj

...  (set-content-view! (*a)
       [:linear-layout {:orientation :vertical}
                         [:edit-text {:id ::name-et
                                      :hint "some stuff"}]
                         [:button {:text "Submit"}]]))))      

neko - defactivity

Activity lifecycle methods (eg. onCreate)

neko - UI

set-content-view! <UI tree as a vector>

neko - UI

XML to Vectors correspondence

neko - UI

<LinearLayout

     android:orientation="vertical">

     <TextView

          android:text="@string/hello"

          android:background="#ffffff" />

</LinearLayout>

neko - UI

[:linear-layout  
     {:orientation :vertical}
     [:text-view 
          {:text "Hello"
           :background-color

                 (Color/parseColor "#ffffff")
           :layout-width :fill}]]

neko - UI

<LinearLayout>

=

[:linear-layout]

neko - UI

android:orientation="vertical"

=

{:orientation :vertical}

neko - UI

This is a Neko Trait

{:orientation :vertical}

neko - UI

If a symbol is not available as a Neko Trait...

{:background-color

        (Color/rgb 20 20 20)}

neko - UI

...interop will use reflection:

 

.setBackgroundColor ...

How to structure for REPL Development

REPL Development

Import Android classes in (:import <android.class>)

REPL Development

If you forgot to import one you can still REPL (class/method ...)

REPL Development

C-x C-e on (on-ui...) will re-evaluate the activity's UI

REPL Development

on-ui is automatically wrapped in neko.debug/safe-for-ui

REPL Development

Keep your emulator in view, errors will show up as Toasts

REPL Development

Example

I'm writing a series of articles describing making a Clojure Android app in detail on 

www.lambdacat.com

Ping me at

@doppioslash

@lambda_cat

You can also get help at

#clojure-android@freenode

(thanks alexyakushev!)

Made with Slides.com