ListViewの1行を表示するViewControllerを書いてみる

ボキャブラリーが貧弱でアレなんだけども、やりたいことはそんな感じ。
リスとビューの1行に表示するアイテムのViewCOntrollerを書いてみる。
1行に前回定義したArticleを表示する予定なので、そういう文脈になっている。

findViewById()ではないKotlin風のViewの取り方

findViewById()を使うことで、IDから該当するViewを取ることができるけれど、
その応答値はnullableなので、findViewById()を使って取ったViewを使いまわそうとすると、
nullableに対するケアがつきまとうようになる。

Kotlinのlazy()を使うことでnullableでないViewの取り方を実現できる!
lazy()は移譲プロパティの移譲先を書く書き方。公式の仕様はこちら
遅延プロパティ、つまりアクセスされたときに初めて評価されるプロパティを実現する。

以下、Viewに<T: View&gt bindView(@IdRes id:Int)という拡張関数を追加している。
追加した拡張関数の戻りがnullを許容しないから、
これを経由すればnullのケアをしなくて良くなる(という話)
lazy()の中で評価したfindViewById()がnullを返した場合、ダウンキャストの失敗を
どう扱うんだろうか。


package com.example.ikuty.myapplication

import android.support.annotation.IdRes
import android.view.View

fun  View.bindView(@IdRes id: Int): Lazy = lazy {
    findViewById(id) as T
}

実装

この拡張関数を使ったArticleViewは以下。
プロパティとして保持するViewがnull非許容になっている。
それにより、setArticle(artilce:Article)において、
プロパティにアクセスする際にnullのケアをしないで済んでいる。

これは便利なんじゃなかろうか。


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)
    }
}