geecon - improve your android-fu with kotlin

52
Power-up your Android-Fu with Kotlin @nicolas_frankel Nicolas Fränkel, 12 May 2016

Upload: nicolas-frankel

Post on 17-Jan-2017

639 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Geecon - Improve your Android-fu with Kotlin

Power-up your Android-Fu with Kotlin

@nicolas_frankel

Nicolas Fränkel, 12 May 2016

Page 2: Geecon - Improve your Android-fu with Kotlin

Me, Myself and IBlah, blah, blah…

@nicolas_frankel #kotlin #android

Page 3: Geecon - Improve your Android-fu with Kotlin

My experience in AndroidBack-end Java developer

Developing a To Do list application with some improvements

Images

Alarm

Multiple lists@nicolas_frankel #kotlin #android

Page 4: Geecon - Improve your Android-fu with Kotlin

My personal viewDeveloping Android app is a pain

Backend Java is very mature compared to Android

High-level libraries required to cope up with low-level APIs

@nicolas_frankel #kotlin #android

Page 5: Geecon - Improve your Android-fu with Kotlin

Starting stackDagger 2

Butterknife

Retro-lambda

Streams

Green Robot’s EventBus

Picasso@nicolas_frankel #kotlin #android

Page 6: Geecon - Improve your Android-fu with Kotlin

OutlineKotlin - the language

Libraries

Stdlib

Kotlin extensions for Android

Anko

@nicolas_frankel #kotlin #android

Page 7: Geecon - Improve your Android-fu with Kotlin

KotlinLanguage developed by JetBrains

Open Source

Compiles to

JVM bytecode

JavaScript (experimental)

A "simpler Scala"@nicolas_frankel #kotlin #android

Page 8: Geecon - Improve your Android-fu with Kotlin

KotlinFunctional and object-orientedStatically typedNull safetyNo checked exceptionsNamed & optional argumentsLambdasExtension functionsJava compatibility(And more...)

@nicolas_frankel #kotlin #android

Page 9: Geecon - Improve your Android-fu with Kotlin

Hello world!package hello // optional semicolons

// namespace-level functions// types on the right// no special syntax for arrays// optional return typefun main(args: Array<String>) { println("Hello, world!")}

@nicolas_frankel #kotlin #android

Page 10: Geecon - Improve your Android-fu with Kotlin

Setup - build.gradlebuildscript { ext.kotlin_version = '1.0.0-beta-1038' repositories { jcenter() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" }}

@nicolas_frankel #kotlin #android

Page 11: Geecon - Improve your Android-fu with Kotlin

Setup – app/build.gradleapply plugin: 'kotlin-android'

android { sourceSets { main.java.srcDirs += 'src/main/kotlin' test.java.srcDirs += 'src/test/kotlin' }}

@nicolas_frankel #kotlin #android

Page 12: Geecon - Improve your Android-fu with Kotlin

Sample codepublic class AddTaskEvent extends AbstractTaskEvent {

private final List list;

public AddTaskEvent(Task task, List list) { super(task); this.list = list; }

public List getList() { return list; }} @nicolas_frankel #kotlin #android

Page 13: Geecon - Improve your Android-fu with Kotlin

Pain pointsVerbose!

Not specific to Android

Unfortunately Java

@nicolas_frankel #kotlin #android

Page 14: Geecon - Improve your Android-fu with Kotlin

Kotlin solutionclass AddTaskEvent(task: Task, val list: List)

: AbstractTaskEvent(task)

@nicolas_frankel #kotlin #android

Page 15: Geecon - Improve your Android-fu with Kotlin

Sample codepublic class KeyboardDisplay {

public void show(Activity a) { InputMethodManager imm = (InputMethodManager) a.getSystemService(INPUT_METHOD_SERVICE); imm.toggleSoftInput(SHOW_FORCED, 0); }

public void hide(Activity a) { InputMethodManager imm = (InputMethodManager) a.getSystemService(INPUT_METHOD_SERVICE); imm.toggleSoftInput(HIDE_IMPLICIT_ONLY, 0); }}

@nicolas_frankel #kotlin #android

Page 16: Geecon - Improve your Android-fu with Kotlin

Pain pointsArtificial grouping

Utility class

No state so not a real Object

@nicolas_frankel #kotlin #android

Page 17: Geecon - Improve your Android-fu with Kotlin

Kotlin solutionfun show(a: Activity) { val imm = a.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager imm.toggleSoftInput(SHOW_FORCED, 0)}

fun hide(a: Activity) { val imm = a.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager imm.toggleSoftInput(HIDE_IMPLICIT_ONLY, 0)}

Page 18: Geecon - Improve your Android-fu with Kotlin

Sample code• SQLiteDatabase db = getReadableDatabase();

db.query(TASK_TABLE, new String[] { T_ID_COL, T_NAME_COL }, null, null, null, null, T_PRIO_COL);

@nicolas_frankel #kotlin #android

Page 19: Geecon - Improve your Android-fu with Kotlin

Pain pointsReally, pass all those null values?

Create local variable for ease of use

@nicolas_frankel #kotlin #android

Page 20: Geecon - Improve your Android-fu with Kotlin

Kotlin solution – part 1fun SQLiteDatabase.query(table:String, columns:Array<String>, selection:String? = null, selectionArgs:Array<String>? = null, groupBy:String? = null, having:String? = null, orderBy:String? = null): Cursor { return query(table, columns, selection, selectionArgs, groupBy, having, orderBy)}

@nicolas_frankel #kotlin #android

Page 21: Geecon - Improve your Android-fu with Kotlin

Kotlin solution – part 2readableDatabase.query(TASK_TABLE,

arrayOf(T_ID_COL, T_NAME_COL), orderBy = T_PRIO_COL)

@nicolas_frankel #kotlin #android

Page 22: Geecon - Improve your Android-fu with Kotlin

One-use private method

@nicolas_frankel #kotlin #android

Page 23: Geecon - Improve your Android-fu with Kotlin

Kotlin solutionNested methods

@nicolas_frankel #kotlin #android

Page 24: Geecon - Improve your Android-fu with Kotlin

Kotlin LibraryStandard API for the language

@nicolas_frankel #kotlin #android

Page 25: Geecon - Improve your Android-fu with Kotlin

Setup – app/build.gradledependencies {

compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

}

@nicolas_frankel #kotlin #android

Page 26: Geecon - Improve your Android-fu with Kotlin

Sample codepublic class DisplayMetricsGetter {

public DisplayMetrics getFrom(Context c) { WindowManager wm = (WindowManager) c.getSystemService(WINDOW_SERVICE); DisplayMetrics metrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(metrics); return metrics; }}

@nicolas_frankel #kotlin #android

Page 27: Geecon - Improve your Android-fu with Kotlin

Pain pointsUtility class

Cannot return the object directly

Have to create a local variable

@nicolas_frankel #kotlin #android

Page 28: Geecon - Improve your Android-fu with Kotlin

Kotlin solutionfun getFrom(c: Context): DisplayMetrics { val wm = c.getSystemService(Context.WINDOW_SERVICE) as WindowManager val metrics = DisplayMetrics() wm.defaultDisplay.getMetrics(metrics) return metrics}

@nicolas_frankel #kotlin #android

Page 29: Geecon - Improve your Android-fu with Kotlin

Kotlin solutionfun getFrom(c: Context): DisplayMetrics { val wm = c.getSystemService(Context.WINDOW_SERVICE) as WindowManager return DisplayMetrics().apply { wm.defaultDisplay.getMetrics(this) }}

@nicolas_frankel #kotlin #android

Page 30: Geecon - Improve your Android-fu with Kotlin

Kotlin extensions for Android

Plugin for the Kotlin compiler

Provide a "synthetic property" for each widget in a layout

@nicolas_frankel #kotlin #android

Page 31: Geecon - Improve your Android-fu with Kotlin

Setup – app/build.gradlebuildscript { repositories { jcenter() } dependencies { classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" }}

@nicolas_frankel #kotlin #android

Page 32: Geecon - Improve your Android-fu with Kotlin

Sample Codepublic class AActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstState) { super.onCreate(savedInstaState); setContentView(R.layout.task_add_item); View imageView = findViewById(R.id.new_task_img); imageView.setOnClickListener(...); }}

@nicolas_frankel #kotlin #android

Page 33: Geecon - Improve your Android-fu with Kotlin

Sample Code – With Butterknifepublic class AddActivity extends AppCompatActivity {

@Bind(R.id.new_task_img) View imageView;

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.task_add_item); ButterKnife.bind(this); imageView.setOnClickListener(...); }} @nicolas_frankel #kotlin #android

Page 34: Geecon - Improve your Android-fu with Kotlin

Pain pointsDo I have to detail???

@nicolas_frankel #kotlin #android

Page 35: Geecon - Improve your Android-fu with Kotlin

Kotlinx solutionimport kotlinx.android.synthetic.task_add_item.new_task_img

class AddTaskActivity : AppCompatActivity() {

override fun onCreate(savedInstState: Bundle?) { super.onCreate(savedInstState) setContentView(R.layout.task_add_item) new_task_img.setOnClickListener(...) }} @nicolas_frankel #kotlin #android

Page 36: Geecon - Improve your Android-fu with Kotlin

AnkoKotlin library for Android

Meant to replace XML with fluent DSL for GUI

But a lot of other niceties

@nicolas_frankel #kotlin #android

Page 37: Geecon - Improve your Android-fu with Kotlin

Code samplepublic class AddAlarmClickListener implements View.OnClickListener {

@Override public void onClick(View view) { View rootView = view.getRootView(); ViewFlipper flip = (ViewFlipper) rootView.findViewById(R.id.new_task_flip); flip.setDisplayedChild(1); }}

@nicolas_frankel #kotlin #android

Page 38: Geecon - Improve your Android-fu with Kotlin

Pain pointsCast

Setter (?)

@nicolas_frankel #kotlin #android

Page 39: Geecon - Improve your Android-fu with Kotlin

Anko solutionimport org.jetbrains.anko.*

class AddAlarmClickListener: View.OnClickListener {

override fun onClick(view: View) { val parent:View = view.rootView val flip = parent.find<ViewFlipper>(R.id.new_task_flip) flip.displayedChild = 1 }} @nicolas_frankel #kotlin #android

Page 40: Geecon - Improve your Android-fu with Kotlin

Code samplefun show(a: Activity) { val imm = a.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager imm.toggleSoftInput(SHOW_FORCED, 0)}

fun hide(a: Activity) { val imm = a.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager imm.toggleSoftInput(HIDE_IMPLICIT_ONLY, 0)}

Page 41: Geecon - Improve your Android-fu with Kotlin

Pain pointsMap-based API

Cast

@nicolas_frankel #kotlin #android

Page 42: Geecon - Improve your Android-fu with Kotlin

Anko solutiona.inputMethodManager.toggleSoftInput( SHOW_FORCED, 0)a.inputMethodManager.toggleSoftInput( HIDE_IMPLICIT_ONLY, 0)

@nicolas_frankel #kotlin #android

Page 43: Geecon - Improve your Android-fu with Kotlin

Code sampleAlertDialog.Builder builder = new AlertDialog.Builder(activity);builder.setMessage("New list name");EditText editText = new EditText(activity);editText.setId( android.support.v7.appcompat.R.id.select_dialog_listview);String listName = global.getList().getName();editText.setText(listName, NORMAL);editText.selectAll();builder.setView(editText);builder.setPositiveButton("OK", editListNameListener);builder.setNegativeButton("Cancel", (dialog, which) -> { dialog.cancel();});AlertDialog dialog = builder.create();dialog.show();

@nicolas_frankel #kotlin #android

Page 44: Geecon - Improve your Android-fu with Kotlin

Pain pointsVerbose +++

Not structured

@nicolas_frankel #kotlin #android

Page 45: Geecon - Improve your Android-fu with Kotlin

Anko solutionview.context.alert('New list name') { builder.setPositiveButton('OK', editListNameListener) negativeButton('Cancel') { cancel() } customView { editText(global.list.name) { id = an.sup.v7.appcompat.R.id.select_dialog_listview }.selectAll() }}.show()

@nicolas_frankel #kotlin #android

Page 46: Geecon - Improve your Android-fu with Kotlin

Final stackDagger 2

Butterknife Kotlin ext.

Retro-lambda Kotlin

Streams Kotlin

Green Robot’s EventBus

Picasso@nicolas_frankel #kotlin #android

Page 47: Geecon - Improve your Android-fu with Kotlin

Migration tacticsStart with standard classesThen with Android-dependent classes

Use Android Studio provided migration toolTake a classMigrate to Kotlin extensionMigrate to AnkoAfter each single change, test!

Repeat

@nicolas_frankel #kotlin #android

Page 48: Geecon - Improve your Android-fu with Kotlin

PitfallNull-able types

@nicolas_frankel #kotlin #android

Page 49: Geecon - Improve your Android-fu with Kotlin

Null-able vs. non null-able typesDifferent type whether value can be

null or not

T: cannot be null

T?: can be null

@nicolas_frankel #kotlin #android

Page 50: Geecon - Improve your Android-fu with Kotlin

Null-able vs. non null-able typesParameter types should use the right

kind

Know your API

Or read the docs

Or be conservative

@nicolas_frankel #kotlin #android

Page 51: Geecon - Improve your Android-fu with Kotlin

My experienceMore expressive

Higher-level abstractions

One single class I couldn’t migrate

Dagger 2 module

@nicolas_frankel #kotlin #android

Page 52: Geecon - Improve your Android-fu with Kotlin

Q&Ahttp://blog.frankel.ch/

@nicolas_frankel

http://frankel.in/

@nicolas_frankel #kotlin #android