Kotlinのスコープ関数を使い分けたい
Kotlin — A deeper look – Hacker Noon より
この図分かり易いと思ってディスプレイに貼ってる。
この図↓も貼ることにした。(2017/10/05追記)
データクラスの話/スコープ関数の話 #rkt - Speaker Deck より
とてもわかりやすい!
この図↓も追加(2018/7/25追記)
Kotlin Demystified: What are 'scope functions' and why are they special? より
以下は自分用の調べたり人から聞いたりしたことのだらだらめも
let
public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
- 最後の値が戻り値になる
- 自身がクロージャの引数になる
- nullableのunwrapによく使う
- 引数として関数をとる
- 変換(convert)に向いてる
- イメージ
- ◯ func(it)
- ✖️it.func()
run
public inline fun <T, R> T.run(block: T.() -> R): R = block()
- クロージャ内の最後の実行結果がrun()の戻り値になる
- letとwithが合わさったような定義
- 任意の型Tの拡張関数で、そのTをレシーバとするメソッドのような関数を引数に取る必要がある
- レシーバーのプロパティとかガンガン使ってなにかする場合に向いてる
- イメージ
- ◯ this.func()
- ✖️func(this)
apply
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
- 返り値は自分自身。なので何か処理を施して自分に返したい時に使う。
- Fragmentのインスタンスを作って、argumentsをセットする時など、 オブジェクトのインスタンスを生成して、 すぐにいくつかのプロパティを初期化する必要がある場合に向いてる
class RoomActivity : AppCompatActivity() { companion object { private const val EXTRA_ROOM_ID = "extra_room_id" fun createIntent(context: Activity, roomId: Int) = Intent(context, RoomActivity::class.java).apply { putExtra(EXTRA_ROOM_ID, roomId) } }
with
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
- not 拡張関数
- 第一引数に任意の型Tを取る。
- 第二引数に関数を取るが、Tをレシーバとする関数である必要がある
- applyと似てる
- with:最後の実行式を返す
- apply:自身を返す
- イメージ:英語の意味で考えると分かり易いかも(〜を使って何かをする)
also
public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }
たろうさんの記事がわかり易かったのでほぼ引用させていただきます。
applyとほぼ同じ。異なる点は「引数が元のレシーバ("hoge")の拡張関数ではなく、元のレシーバを引数に取る関数である」ところ。 その利点は2つ
①名前を付けられるのでコードの可読性が上がる
②ラムダ式の内と外でthisの意味が変わらない
// applyを使用 val button = Button(this).apply { text = "Click me" setOnClickListener { startActivity(Intent(this@MainActivity, NextActivity::class.java)) // 単なる「this」ではNG ^ } }
// alsoを使用 val button = Button(this).also { button -> button.text = "Click me" button.setOnClickListener { startActivity(Intent(this, NextActivity::class.java)) } }
同じく「元のレシーバを引数に取る関数」を引数に取るletとの違いは、letは戻り値を自分で決めるのに対し、alsoは元のレシーバが返されるという点
// letを使用 val button = Button(this).let { button -> button.text = "Click me" button.setOnClickListener { startActivity(Intent(this, NextActivity::class.java)) } button // letの場合はこれが必要になる }
めもここまで。
というわけで、やっぱりよくわからん!!!!!\(^o^)/
色んな人に使い分け方聞いてる*1んですが、 人によって微妙に使いどころ(捉え方?)違うような印象だったり・・・
英語の意味を考えて使うようにすると前よりしっくりきた。。ような気がする
まだまだ理解足りてないのでご指摘・補足等ございましたら遠慮なくお願いいたします🙇🙇
参考サイト
Kotlin — A deeper look – Hacker Noon
http://qiita.com/ngsw_taro/items/d29e30809fc8a38691e
Kotlin 1.1で追加された標準ライブラリの関数をざっくり見る - visible true
*1:①返り値を使わない+何か初期化とかするときはwithで、自分自身が欲しい場合はapply、返り値を使いたいときはrun or letみたいな感じ
RxJava入門してきた
こちらに参加してきましたという感想文です。
自分のRxレベルはAPI周りの非同期処理を見よう見まねで触れ出した初心者レベル。
入門者向けの内容だったので正直ありがたかったです🙏
RxJavaは1から2への移行がなかなか苦労する(null が非許容になった等)ということは耳にしていたので、 今からやるなら何も意識せずRxJava2を使った方がいいそう。
お話の中で印象的だったのは、黒川さんがイメージするRxJavaは、よく言われる川の流れというより、 排水管の流れをキュッとコントロールするイメージだそう。
確かに自分もそっちの方がしっくりくるかも
あとオペレータは黒川さんも把握できてないほど種類が多いとか、、
当日の課題はこちら
RxJavaってどう課題にするんだろう🤔と思ってたけど、Android要素が取り入れられてて、 しかも業務で活かせそうな内容で大変有り難いです🙏
入門者はやってみると良いと思います!
あと図々しく質問したらこんなお返事いただけました🙇🙇
いえいえ。UI周りだと、サジェストを出すときに使ったりします。サジェストの取得とテキスト入力両方を同時に扱いたいときに便利です。
— Hiroshi Kurokawa (@hydrakecat) 2017年6月29日
まだRxJavaは出来ることが多すぎて混乱中ですが、うまくキュキュッとコントロールできるようになりたいものです。
sketch用アプリCrystal便利
同じWifi環境に繋げばアートボードをミラーリングしてくれる
Android5.0以上対応
参考:Android端末でSketchをリアルタイムプレビューするアプリ「Crystal」の紹介 | テクニカルクリエイター.com
ダイエットを頑張った話
speakerdeck.com をしてきた。
結局今のサイズは…?
施策が増えたりでちょっと太ってしまったのですが現状は 6.1M です。 ので一番太ってたころと比べると1/4ほどになりました
反省点
- apkサイズはもっと減らせる筈(proguard設定はもう少し見直せそう)
- Zeplinいいぞ話が時間足りなくて出来なかった(今更感あるけど、便利機能が追加されてるので実際見せて紹介したかった)
- Layout階層のダイエット話もしたかった(諸々間に合わなかった)
- 自分のダイエットには失敗した…泣
教えていただけた他のダイエット方法
- ロケールを絞る
→ 日本オンリーの仕様ならこんなことができるみたいです。知らなカッタ…
赤字部分を追加でライブラリにあるja以外のstringsを弾いてくれる模様
build.gradle
defaultConfig {
minSdkVersion 15
…
resConfigs "ja"
}
試してみたら500kBほど減りました
→こちらは未だ試せてないけど試してみたいです🙏さらにアプリがMulti Dex化してるなら、Single Dexまで頑張るとさらにアプリサイズ軽くなるかもなー / “application diet // Speaker Deck” https://t.co/LoGOlyhTxj
— shinobu.apk (@operandoOS) 2017年4月21日
setCustomAnimationsが効かなくてハマってた
FragmentTransactionに設定する順番が原因。 .addの後に.setCustomAnimationsしてのが問題だった。
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction
.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right,
android.R.anim.slide_in_left, android.R.anim.slide_out_right)
.add(R.id.content_container, new Fragment())
.addToBackStack(null)
.commit();
これで解決。ハマったー泣
RecyclerViewの中でPopupMenuするとscrollしちゃう問題
こうなっちゃって困ってた
ボタン押したらにゅるって動いちゃう
↓
android.support.v7.widget
じゃなくてandroid.widget.PopupMenu
を使ったら解決した。
ちゃんとわかってないけどv7のバグってことでいいのかな?
android - PopupMenu click causing RecyclerView to scroll - Stack Overflow
VectorDrawableをさっくり触った話
droidgirls.connpass.com
こちらに参加してきたので感想などなど
VectorDrawable触ったことなかったけど、
講師のこにふぁーさんの解説と用意してきてくださった課題のおかげで
短い時間でさっくり動かすことができた。自分の整理用に書く
こちら当日のありがたいスライド(というか全てはここに書いてある)
speakerdeck.com
VectorDrawableについてざっくり
VectorDrawableを使うとapkサイズが削減できる
SVG(Scalable Vector Graphics)を使っているのでpngなどのビットマップデータと違い、拡大しても画像が荒くなったりせず綺麗 → 今まで端末サイズ毎に用意してきたpngファイルを一つにできる。
Lollipop(API Level 21)未満もsupportされた
※Support Library23.2〜
但しanimatedVectorDrawableのmorphing animationは未だsupportされていない
(ただLollipop未満でも同じように動かせる方法もあるらしいとのこと)
逆にVectorDrawable使うべきじゃない時
大きい画像の場合(googleさん規定では200 × 200 より大きい画像)
また色や形状が複雑な画像の場合は初回読み込みが遅くなる
VectorDrawable使い方
svgファイル取得
一般的なデザインツール(sketchやadobe製品)なら大体svg吐き出しツールがある
GoogleのMaterial Designはすでに用意されてるものがある → https://design.google.com/icons
svgからXMLを作成
Android Studioの New > Vector Asset でXML作成してdrawableに吐き出してくれる
サイズは(きっと)小さければ小さいほど良いらしい
XMLをImageViewに設定
できたものをImageViewのandroid:src
をapp:srcCompat
に変えて指定
srcから設定するときはsetImageResource()
を使う
toolbarのメニューiconでも使用できる
※TextView内で画像指定するときは別途selectorファイルを作ってそれを指定する
- その他詳細やGradleの設定などはこちらを VectorDrawable対応まとめ - Qiita
AnimatedVectorDrawable使い方
XMLファイルを用意
① vector drawable
② animator
③ AnimatedVectorDrawable:①を@drawable
に指定、②をtarget
の@animator
に指定
※ ①と③のnameを同じものにしなくてはいけない★
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="48dp" android:height="48dp" android:viewportHeight="48.0" android:viewportWidth="48.0"> <path android:name="pause"★ android:fillColor="#000000" android:pathData="@string/path_pause" /> </vector>
<animated-vector android:drawable="@drawable/ic_pause_48dp"> <target android:name="pause"★ android:animation="@animator/anim_pause_to_play" /> </animated-vector>
※ 新しい書き方ではXMLは③のみでOKになった
srcにて③をImageViewに設定しstart()
Drawable drawable = imageView.getContext().getDrawable(③); imageView.setImageDrawable(drawable); Animatable animatable = (Animatable) drawable; animatable.start();
toolなど
- AnimatedVectorDrawableを生成してくれる神ツール
AndroidIconAnimator :https://romannurik.github.io/AndroidIconAnimator/ - pathなのでぱっと見形がわからないVectorDrawableをPullRequest上でプレビューしてくれる Chrome Extension
https://github.com/jmatsu/vector-drawable-previewer
詰まったところ
AnimatedVectorDrawableの③の書き方をすると
Element animated-vector doesn't have required attribute android:drwable
だのattribute is missing the android namespace prefix
だのエラーが出る
→ 現状のAndroid studio(ver 2.2.3)の対応が追いついてないだけのようで、エラーは出るがこれで動く5未満の端末でTextViewのandroid:drawableLeftで落ちる
→ StateListDrawableを作成してその中でVectorDrawableを指定してあげる必要がある(※参考)
→ 使用するActivityで以下の呼び出しが必要
static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); }
感想
- Lollipop未満もサポートされたってことでアイコン系はVectorDrawableに置き換えてどれだけサイズ減るか試してみたい
- vectorファイルの命名がgoogleサンプルの
ic_〜〜_[size]dp.xml
が一般的?みたいだけどなんか気持ち悪い、皆さんどうしてるんだろう - AndroidIconAnimatorでファイル作ってみようとしたけど簡単なことしかできなかったムズイ(;・∀・) 出来たら書きますっ
- pathの仕組みの解説をこにふぁーさんが「ね、簡単でしょ」的にしてたけど難しかった😭
- こちらの用意してくださったサンプルコードが入門向けにとてもわかりやすかったです
こにふぁーさんありがとうございました!!!
何か間違ってたらご指摘お願いしますm(__)m