LoginSignup
3
0

More than 1 year has passed since last update.

AndroidでViewBindingを使ってみる

Posted at

ViewBindingとは・・・?なんじゃんねぇ?

AndroidではLayout xmlとJavaかkotlinのソースが別々で、Layout xmlでは各Viewにidを振ります。

android:id="@+id/xxxbutton"

それをJavaかkotlinのソース側から

val button = findViewById(R.id.xxxbutton)

といった風に参照します。AndroidではkotlinだとViewBindingという方法が使えます。

参考:
公式Android developers ビューバインディング

ViewBindingのメリットは?

findViewById と ViewBindingを比較した場合のメリットは

  • null の安全性が高まる。
    • 無効なビュー ID によって NullPointerException が発生することがない。findViewByIdはidを間違えるとnullが返ってきます。(idはInt型であればなんでもいい)
  • 型の安全性
    • XML ファイル内で参照しているビューがclassに変換され、型を持ちます。バインディングクラス内のフィールドは、レイアウトファイルの型と一致します。そのため、ClassCastException が起きることがない。(無理に違う型に操作しようとすると、コンパイル時にわかる)

大きく分けて以上の2点のメリットが有ります。googleもViewBindingはfindViewByIdの後継として推奨しているようです。

ここで以前から勘違いしていたことに気がつく。

layout xmlのidですが、AndroidStudioが他のlayout xmlで使っているidと重複していると、警告を出してくるので
Screenshot_20221128_210427.png
今まで、idは全てのlayout xmlを通してユニークでなければならないんだと思っていました。(なので、idの名前の付け方が悩ましかった・・・)
R.id.xxxと、いった具合に、R.idの下にフラットにできるのでそうなんだろうなと思っていました。
ところが、idはlayout xmlを通して重複していても何ら問題ありません。ちゃんと動きます。(じゃ、何でAndroidStudioはあんな警告出すんだ?)
オマケに同一のlayout xmlの中で重複していても、ビルドエラーにもなりません。動きます。ただ、おそらく、実行時に先に見つけた方のViewのidで動いているんだと思います。

なので・・・
ViewBindingなると、idの重複の制約がなくなって、やりやすくなった・・・と思ってましたが、それはfindViewByIdもViewBindingも、一緒でした。

ViewBindingを使えるようにするためには

ViewBindingはデフォルトでは有効になっていません。build.gradleに追記する必要があります。公式ホームページにもありますが2通りの指定方法があります。

build.gradle
android {
   (中略)
    viewBinding {
        enabled = true
    }
}
build.gradle
android {
   (中略)
    buildFeatures {
        viewBinding true
    }
}

僕はいつも上のやり方でやっています。修正してgradle同期すると使えるようになります。同期すると、layout xmlのファイル名に対応したclassができあがります。今、2つあるlayout xmlに対して
Screenshot_20221128_212208.png
buildの下に2つのクラスができています。
Screenshot_20221128_212114.png
ネーミングはだいたい想像が付きますが、layout xmlのファイル名はキャメルケースに変換して、その後ろにBindingが付きます。

ActivityでViewBindingを使う場合

ActivityでそれはfindViewByIdの場合は

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val txt: TextView = findViewById(R.id.helloTxt)
    }
}

ViewBindingだと

class MainActivity : AppCompatActivity() {
     lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        val txt = binding.helloTxt
    }
}

といった書き方になります。

FlagmentでViewBindingを使う場合

Flagmentの場合はちょっと複雑です。findViewByIdの場合は,

class BlankFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_blank, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val txt: TextView = view.findViewById(R.id.helloTxt)
    }
}

ViewBindingだと

class BlankFragment : Fragment() {
    private var _binding: FragmentBlankBinding? = null
    private val binding get() = _binding!!
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentBlankBinding.inflate(inflater, container, false)
        return binding.root
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val txt = binding.helloTxt
    }
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

といった書き方になります。

で、結局、何が嬉しいの?

これだけを見るとViewBindingの方が若干、長くなっているんじゃないの?と思うかもしれませんが、上に上げた2つのメリットである、null の安全性、型の安全性を考えると使う価値はあるかと思います。
ViewBindingはキャッシュしてくれるので、findViewByIdよりも若干性能がいいという話も有ります。

簡潔かどうかという麺では

val txt: TextView = findViewById(R.id.helloTxt)
val txt = binding.helloTxt

ここだけを見ると、ViewBindingの方が簡潔であると言えます。(無理あるかなー)
ボタンのイベントリスナを設定する場合とかは

binding.button.setOnClickListener {
    ・・・
}

で一気に書いちゃう場合が多いです。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0