ボキャブラリーが貧弱でアレなんだけども、やりたいことはそんな感じ。
リスとビューの1行に表示するアイテムのViewCOntrollerを書いてみる。
1行に前回定義したArticleを表示する予定なので、そういう文脈になっている。
findViewById()ではないKotlin風のViewの取り方
findViewById()を使うことで、IDから該当するViewを取ることができるけれど、
その応答値はnullableなので、findViewById()を使って取ったViewを使いまわそうとすると、
nullableに対するケアがつきまとうようになる。
Kotlinのlazy()を使うことでnullableでないViewの取り方を実現できる!
lazy()は移譲プロパティの移譲先を書く書き方。公式の仕様はこちら。
遅延プロパティ、つまりアクセスされたときに初めて評価されるプロパティを実現する。
以下、Viewに<T: View> bindView(@IdRes id:Int)という拡張関数を追加している。
追加した拡張関数の戻りがnullを許容しないから、
これを経由すればnullのケアをしなくて良くなる(という話)
lazy()の中で評価したfindViewById()がnullを返した場合、ダウンキャストの失敗を
どう扱うんだろうか。
1 2 3 4 5 6 7 8 |
package com.example.ikuty.myapplication import android.support.annotation.IdRes import android.view.View fun <T: View> View.bindView(@IdRes id: Int): Lazy<T> = lazy { findViewById(id) as T } |
実装
この拡張関数を使ったArticleViewは以下。
プロパティとして保持するViewがnull非許容になっている。
それにより、setArticle(artilce:Article)において、
プロパティにアクセスする際にnullのケアをしないで済んでいる。
これは便利なんじゃなかろうか。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
package com.example.ikuty.myapplication.view import android.content.Context import android.graphics.Color import android.util.AttributeSet import android.view.LayoutInflater import android.widget.FrameLayout import android.widget.ImageView import android.widget.TextView import com.example.ikuty.myapplication.R import com.example.ikuty.myapplication.model.Article import com.example.ikuty.myapplication.bindView class ArticleView : FrameLayout { constructor(context: Context?) : super(context) constructor(context: Context?, attrs: AttributeSet?) : super(context,attrs) constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context,attrs,defStyleAttr) constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context,attrs,defStyleAttr,defStyleRes) val profileImageView: ImageView by bindView(R.id.profile_image_view) val titleTextView: TextView by bindView(R.id.title_text_view) val userNameTextView: TextView by bindView(R.id.user_name_text_view) init { LayoutInflater.from(context).inflate(R.layout.view_article,this) } fun setArticle(article: Article) { titleTextView.text = article.title userNameTextView.text = article.user.name profileImageView.setBackgroundColor(Color.RED) } } |