🐞

ViewBindingを使用してMainActivityの中でレイアウトの設定を行う

2025/03/20に公開

kotlin初学者なため、間違い等があれば教えていただけますと幸いです。

環境
Android Studio Ladybug Feature Drop | 2024.2.2
compileSdk 35
kotlin 1.9.24

前回の記事のソースをもとに進めていきます。
KotlinでAPI通信を行う

XMLレイアウトへアクセスする

findViewByIdやViewBindindとは?

findViewByIdやViewBindingを使用すると、XMLレイアウトに定義された各UIコンポーネントに、ActivityやFragmentから簡単にアクセスでき、その属性や動作を変更することが可能になります。
今回はfindViewById を使わず、ViewBindingを使ってレイアウトファイル内のビュー(idで指定されたUIコンポーネント)を取得しています。

ViewBindingを有効にする

build.gradleに以下を追加します。
これで、ViewBindingを使うことができるようになります。

android {
    ...
    buildFeatures {
        viewBinding = true
    }
}

MainActivityと結びつける

private lateinit var binding: ActivityMainBinding
ActivityMainBinding・・・activity_main.xml から自動生成されたバインディングクラス。XMLレイアウト内の各UIコンポーネントにアクセスできるようにします。
binding = ActivityMainBinding.inflate(layoutInflater)
layoutInflater・・・XMLに記述されたUIレイアウトを、プログラムから操作可能な実際のViewオブジェクトに変換します。
inflate()・・・メソッドの引数としてlayoutInflaterを渡すと、生成したViewをどの親コンテナにアタッチするかを指定できます。今回の場合は親コンテナを指定せず、後でsetContentView(binding.root) で明示的にアタッチしています。
最後に、生成されたActivityMainBindingインスタンスをbindingに代入します。
binding.pokeRecyclerView.layoutManager = LinearLayoutManager(this)
LinearLayoutManager(this)・・・RecyclerViewのアイテムを縦方向(デフォルト)に並べます。thisはこの場合、実行中のMainActivityを指します。
binding.pokeRecyclerView.layoutManager・・・ activity_main.xmlに定義されたRecyclerViewのレイアウト。.layoutManagerプロパティに代入することで、RecyclerViewの表示方法やスクロール動作を管理することができます。

    private lateinit var binding: ActivityMainBinding
    private lateinit var adapter: PokeAdapter
    private val pokemonList = mutableListOf<PokemonResponse>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        WindowCompat.setDecorFitsSystemWindows(window,true)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.pokeRecyclerView.layoutManager = LinearLayoutManager(this)
        adapter = PokeAdapter(pokemonList)
        binding.pokeRecyclerView.adapter = adapter
     .....
    }

PokeAdapterの書き換え

class ViewHolder(val binding: PokeRowBinding) : RecyclerView.ViewHolder(binding.root)
PokeRowBinding・・・poke_row.xmlから『自動生成』されたバインディングクラスです。
binding.root・・・ViewBindingによって生成されたバインディングクラス。今回の場合は、『recyclerview』の『constraintlayout』を指します。

val binding = PokeRowBinding.inflate
inflate(LayoutInflater.from(parent.context),parent,false)・・・XMLファイルに書かれた画面を実際の画面に表示されるViewオブジェクトに変換します。
(inflateの定義)

class PokeAdapter(private val pokemonList: MutableList<PokemonResponse>): RecyclerView.Adapter<PokeAdapter.ViewHolder>(){
    class ViewHolder(val binding: PokeRowBinding) : RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = PokeRowBinding.inflate(
            LayoutInflater.from(parent.context),parent,false
        )
        return ViewHolder(binding)
    }

    override fun getItemCount(): Int = pokemonList.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val pokemon = pokemonList[position]
        holder.binding.pokeTextView.text = pokemon.name
        Glide.with(holder.itemView.context)
            .load(pokemon.sprites.frontDefault)
            .into(holder.binding.pokeImageView)
    }
}

全体

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var adapter: PokeAdapter
    private val pokemonList = mutableListOf<PokemonResponse>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        WindowCompat.setDecorFitsSystemWindows(window,true)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.pokeRecyclerView.layoutManager = LinearLayoutManager(this)
        adapter = PokeAdapter(pokemonList)
        binding.pokeRecyclerView.adapter = adapter

        lifecycleScope.launch {
            for (id in 1..10) {
                try {
                    val pokemon = RetrofitInstance.api.getPokemon(id)
                    pokemonList.add(pokemon)
                    adapter.notifyItemInserted(pokemonList.size - 1)
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }
    }
}

Discussion