1年半プロジェクトでKotlinを使ってみて良かったこと、良くなかったこと(2017-01 CA.apk)

Daec7e5cd5fae384eda88037d937343b?s=47 AAkira
January 12, 2017

1年半プロジェクトでKotlinを使ってみて良かったこと、良くなかったこと(2017-01 CA.apk)

Daec7e5cd5fae384eda88037d937343b?s=128

AAkira

January 12, 2017
Tweet

Transcript

  1. 4.

    Released map M1 2012-04-12 M11 2015-03-19 M14 2015-10-01 1.0-beta4 2015-12-22

    M13 2015-09-16 1.0 2016-02-16 1.0-RC 2016-02-04 2016-01-21 Release 2015-04 開発開始 kotlin FRESH
  2. 7.

    コード量が減る for (int i = 0; i < 10; i++)

    { Log.v("tag", "i=" + i); } int[] array = {0, 10, 20, 30, 40, 50, 60}; for (int item : array) { Log.v("tag", "item=" + item); } for (int i = 0; i < array.length; i++) { Log.v("tag", "item[" + i + "]=" + array[i]); }
  3. 8.

    コード量が減る convert to Kotlin for (i in 0..9) { Log.v("tag",

    "i=" + i) } val array = intArrayOf(0, 10, 20, 30, 40, 50, 60) array.forEach { Log.v("tag", "item=" + it) } array.forEachIndexed { index, item -> Log.v("tag", "item[$index]=$item") }
  4. 10.

    コード量が減る Observable.from(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8,

    9, 10}) .filter(new Func1<Integer, Boolean>() { @Override public Boolean call(Integer i) { return (i % 2) == 0; } }) .map(new Func1<Integer, Integer>() { @Override public Integer call(Integer i) { return i * 10; } }) .subscribe(new Observer<Integer>() { @Override public void onNext(Integer integer) { Log.d("TAG", integer.toString()); } @Override public void onCompleted() { } @Override public void onError(Throwable e) { } });
  5. 11.

    コード量が減る Observable.from(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8,

    9, 10}) .filter(new Func1<Integer, Boolean>() { @Override public Boolean call(Integer i) { return (i % 2) == 0; } }) .map(new Func1<Integer, Integer>() { @Override public Integer call(Integer i) { return i * 10; } }) .subscribe(new Observer<Integer>() { @Override public void onNext(Integer integer) { Log.d("TAG", integer.toString()); } @Override public void onCompleted() { } @Override public void onError(Throwable e) { } }); 20, 40, 60, 80, 100
  6. 12.

    コード量が減る convert to Kotlin Observable.from(arrayOf(1, 2, 3, 4, 5, 6,

    7, 8, 9, 10)) .filter { i -> i % 2 == 0 } .map { i -> i * 10 } .subscribe(object : Observer<Int> { override fun onNext(integer: Int?) { Log.d("TAG", integer.toString()) } override fun onCompleted() {} override fun onError(e: Throwable) {} })
  7. 13.

    コード量が減る Observable.from(arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9,

    10)) .filter { it % 2 == 0 } .map { it * 10 } .subscribe(object : Observer<Int> { override fun onNext(integer: Int?) { Log.d("TAG", integer.toString()) } override fun onCompleted() {} override fun onError(e: Throwable) {} })
  8. 14.

    コード量が減る Observable.from(arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9,

    10)) .filter { it % 2 == 0 } .map { it * 10 } .subscribe({ Log.d("TAG", it.toString()) }, { // onError }, { // onCompleted })
  9. 16.

    拡張関数便利 forEachの正体もこれ /** * Performs the given [action] on each

    element, providing sequential index with the element. * @param [action] function that takes the index of an element and the element itself * and performs the desired action on the element. */ public inline fun <T> Iterable<T>.forEachIndexed(action: (Int, T) -> Unit): Unit { var index = 0 for (item in this) action(index++, item) } /** * Performs the given [action] on each element. */ @kotlin.internal.HidesMembers public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit { for (element in this) action(element) }
  10. 22.

    拡張関数便利 • run • let • apply • (with) 146

    箇所 442 箇所 293 箇所 0 箇所
  11. 30.

    コードの意図が伝わる val hoge = 10 var foo = 100 val

    bar: String if (hoge > 5) { foo = 200 bar = “fresh!" } else { foo = 300 bar = "abema" } Log.v("TAG", "foo=$foo, bar=$bar")
  12. 31.

    コードの意図が伝わる val hoge = 10 var foo = 100 val

    bar: String if (hoge > 5) { foo = 200 bar = “fresh!" } else { foo = 300 bar = "abema" } Log.v("TAG", "foo=$foo, bar=$bar") 定数が一目瞭然
  13. 32.

    コードの意図が伝わる class HogeActivity : Activity { companion object { private

    const val EXTRA_HOGE = "extra_hoge" private const val EXTRA_FOO = "extra_foo" private const val EXTRA_BAR = "extra_bar" fun createIntent(activity: Activity, hoge: Int) = Intent(activity, HogeActivity::class.java).apply { putExtra(EXTRA_HOGE, hoge) } fun createIntent(activity: Activity, foo: String, bar: String? = null) = Intent(activity, HogeActivity::class.java).apply { putExtra(EXTRA_FOO, foo) putExtra(EXTRA_BAR, bar) } } …… }
  14. 33.

    コードの意図が伝わる class HogeActivity : Activity { companion object { private

    const val EXTRA_HOGE = "extra_hoge" private const val EXTRA_FOO = "extra_foo" private const val EXTRA_BAR = "extra_bar" fun createIntent(activity: Activity, hoge: Int) = Intent(activity, HogeActivity::class.java).apply { putExtra(EXTRA_HOGE, hoge) } fun createIntent(activity: Activity, foo: String, bar: String? = null) = Intent(activity, HogeActivity::class.java).apply { putExtra(EXTRA_FOO, foo) putExtra(EXTRA_BAR, bar) } } …… } nullに意味がある
  15. 38.

    アプリがcrashしない var hoge: String? = “hoge" // ΋͠hoge͕nullͩͬͨΒ0 if (hoge?.length

    ?: 0 > 0) hoge = "replace" // ΋͠hoge͕nullͩͬͨΒॳظԽ hoge = hoge ?: "init"
  16. 39.

    アプリがcrashしない class Hoge { var onHogeChangedListener: (() -> Unit)? =

    null fun doSomething() { onHogeChangedListener?.invoke() } } class HogeActivity: Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val hoge = Hoge() hoge.onHogeChangedListener = { } } }
  17. 41.
  18. 44.

    メソッド数が微妙に増える 5142 kotlin
 2 kotlin._Assertions
 12 kotlin.annotation
 2519 kotlin.collections
 65

    kotlin.comparisons
 31 kotlin.concurrent
 6 kotlin.internal
 296 kotlin.io
 549 kotlin.jvm
 24 kotlin.jvm.functions
 506 kotlin.jvm.internal
 2 kotlin.jvm.internal.unsafe
 23 kotlin.properties
 227 kotlin.ranges
 61 kotlin.reflect
 423 kotlin.sequences
 3 kotlin.system
 762 kotlin.text https://github.com/KeepSafe/dexcount-gradle-plugin Kotlin version : 1.06
  19. 50.
  20. 59.
  21. 63.

    Animator Listener fun Animator.setListener( onAnimationStart: (Animator) -> Unit = {},

    onAnimationEnd: (Animator) -> Unit = {}, onAnimationCancel: (Animator) -> Unit = {}, onAnimationRepeat: (Animator) -> Unit = {} ) = apply { addListener(object : Animator.AnimatorListener { override fun onAnimationStart(animation: Animator) { onAnimationStart(animation) } override fun onAnimationEnd(animation: Animator) { onAnimationEnd(animation) } override fun onAnimationCancel(animation: Animator) { onAnimationCancel(animation) } override fun onAnimationRepeat(animation: Animator) { onAnimationRepeat(animation) } }) }
  22. 65.

    Visibility fun View.toVisible() { visibility = View.VISIBLE } fun View.toInvisible()

    { visibility = View.INVISIBLE } fun View.toGone() { visibility = View.GONE }
  23. 67.

    Apply margin fun View.applyMargin(left: Int = 0, top: Int =

    0, right: Int = 0, bottom: Int = 0) = (layoutParams as ViewGroup.MarginLayoutParams).apply { leftMargin = left topMargin = top rightMargin = right bottomMargin = bottom }