Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AndroidでKotlinフル活用プログラミング #Kotlin_Sansan

AndroidでKotlinフル活用プログラミング #Kotlin_Sansan

AndroidでKotlin勉強会 @ Sansan で発表したスライドです。
http://connpass.com/event/22189/

14c9795d267f5b85abb98ca5e8780646?s=128

Taro Nagasawa

January 15, 2016
Tweet

Transcript

  1. AndroidでKotlin フル活用プログラミング 2016-01-15 AndroidでKotlin勉強会 @ Sansan 長澤 太郎 @ngsw_taro

  2. 自己紹介 • 長澤 太郎 @ngsw_taro • 仕事ではAndroidメイン、Java, Scala, Railsなど •

    Kotlinエバンジェリスト(自称) ◦ 講演や執筆などの実績多数 • 27歳、蟹座、ビール大好き
  3. 私のブログ

  4. アプリカティブなんとかみたいなやつ val minus = { a: Int -> { b:

    Int -> a - b } } fun <T, R> T.bind(f: ((T)->R)?): R? = f?.invoke(this) y?.bind(x?.bind(minus)) fun <T, R> ((T)->R).apply(n: T?): R? = n?.bind(this) val sub: Int? = minus.apply(x)?.apply(y) http://taro.hatenablog.jp/entry/2014/04/06/144811
  5. メソッド参照みたいなやつ val <A, B> (A.()->B).tof: (A)->B get() = { a:

    A -> a.this() } listOf("a", "bb", "ccc").map(String::length.tof) http://taro.hatenablog.jp/entry/2015/02/24/215413
  6. Extensionで なんでもするマン

  7. AndroidでKotlin Extensionプログラミング 2016-01-15 AndroidでKotlin勉強会 @ Sansan 長澤 太郎 @ngsw_taro

  8. RxLifecycle面倒

  9. RxLifecycleを使う // in RxAppCompatActivity apiAccesss() .compose(bindToLifecycle<MyData>()) .subscribe { ... }

    省略できないっぽい
  10. こうしたい: 拡張関数使えばできそう // in RxAppCompatActivity apiAccesss() .bindToLifecycle() .subscribe { ...

    }
  11. こういうの作る // in RxAppCompatActivity fun <T> Observable<T>.bindToLifecycle() = compose<T>(self.bindToLifecycle()) いい感じ!

    共通部品化したい
  12. こういう提案 interface RxLifecycleFeature: ActivityLifecycleProvider { fun <T> Observable<T>.bindToLifecycle() = compose<T>(this@RxLifecycleFeature.bindToLifecycle())

    }
  13. 使用側のアクティビティ class MyActivity: RxAppCompatActivity(), RxLifecycleFeature { fun go() { apiAccess()

    .bindToLifecycle() .subscribe {...} } }
  14. 明示的Activity起動の問題

  15. よくあるやつ: 遷移先 class TargetActivity: Activity() { companion object { fun

    intent(c: Context, data: String) = Intent(c, TargetActivity::class.java) .putExtra(“data”, data) } }
  16. よくあるやつ: 遷移元 class SourceActivity: Activity() { fun go() { val

    data = “hogefuga” startActivity(TargetActivity.intent(this, data)) } }
  17. よくあるやつ: 遷移元 class SourceActivity: Activity() { fun go() { val

    data = “hogefuga” startActivity(TargetActivity.intent(this, data)) } } thisを書きたくない! 簡単には拡張関数に できなさそう...
  18. Intent生成を遅らせる: 遷移先 class TargetActivity: Activity() { companion object { fun

    intent(data: String) = { c: Context -> Intent(c, TargetActivity::class.java) .putExtra(“data”, data) } } }
  19. Intent生成を遅らせる: 遷移先 class TargetActivity: Activity() { companion object { fun

    intent(data: String) = { c: Context -> Intent(c, TargetActivity::class.java) .putExtra(“data”, data) } } } Contextを取らなくなった
  20. Intent生成を遅らせる: 遷移先 class TargetActivity: Activity() { companion object { fun

    intent(data: String) = { c: Context -> Intent(c, TargetActivity::class.java) .putExtra(“data”, data) } } } Context -> Intentな 関数を返す
  21. イマイチな使用例: 遷移元 class SourceActivity: Activity() { fun go() { val

    data = “hogefuga” startActivity(TargetActivity.intent(data)(this)) } }
  22. よさげな使用例: 遷移元 class SourceActivity: Activity() { fun go() { val

    data = “hogefuga” TargetActivity.intent(data).start() } fun ((Context)->Intent).start() { startActivity(this(applicationContext)) } }
  23. よさげな使用例: 遷移元 class SourceActivity: Activity() { fun go() { val

    data = “hogefuga” TargetActivity.intent(data).start() } fun ((Context)->Intent).start() { startActivity(this(applicationContext)) } } ここからthisが消えた
  24. 共通部品化する for 遷移先 inline fun <reified T : Activity> intentBuilder(crossinline

    init: Intent.() -> Unit) = { context: Context -> Intent(context, T::class.java).apply { init() } }
  25. 共通部品を使う: 遷移先 class TargetActivity: Activity() { companion object { fun

    intent(data: String) = intentBuilder<TargetActivity> { putExtra(“data”, data) } } }
  26. 共通部品化する for 遷移元 interface IntentFeature { fun startActivity(intent: Intent) fun

    getApplicationContext() fun ((Context)->Intent).start() { startActivity(this(getApplicationContext())) } } インタフェースを継承するので はなく、抽象メソッドを定義して おく
  27. 共通部品を使う: 遷移元 class SourceActivity: Activity(), IntentFeature { fun go() {

    val data = “hogefuga” TargetActivity.intent(data).start() } }
  28. おまけ: M11以前 trait IntentFeature: Activity { fun ((Context)->Intent).start() { startActivity(this(getApplicationContext()))

    } } 実装する側のクラスを 指定できた
  29. Thank you, Enjoy Kotlin!