Search code examples
androidfindviewbyidandroid-viewbinding

How to avoid these tedious findViewById() calls?


I have a simple layout file with two TextViews:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tv_tile_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sample text"
        android:textSize="18dp"
        android:layout_gravity="center_horizontal"/>

    <TextView
        android:id="@+id/tv_tile_value"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:text="20.0"
        android:textSize="26dp"
        android:textStyle="bold" />
</LinearLayout>

I include this layout in some places in my app. In my last case I had to include this 4 times. To find and set text to these two text views in the individual included layouts I have to find an id to one layout and from there find an id to two text views. And repeat 3 times for all included layouts. This leads to some ugly and horrible to maintain code:

@Override
public void setStatsValues(String today, String week, String month, String total) {
    // this is so tedious.
    View layoutDay = findViewById(R.id.layout_stats_day);
    View layoutWeek = findViewById(R.id.layout_stats_week);
    View layoutMonth = findViewById(R.id.layout_stats_month);
    View layoutTotal = findViewById(R.id.layout_stats_total);
    TextView tvDayTitle = layoutDay.findViewById(R.id.tv_tile_title);
    TextView tvWeekTitle = layoutWeek.findViewById(R.id.tv_tile_title);
    TextView tvMonthTitle = layoutMonth.findViewById(R.id.tv_tile_title);
    TextView tvTotalTitle = layoutTotal.findViewById(R.id.tv_tile_title);
    TextView tvDayValue = layoutDay.findViewById(R.id.tv_tile_value);
    TextView tvWeekValue = layoutWeek.findViewById(R.id.tv_tile_value);
    TextView tvMonthValue = layoutMonth.findViewById(R.id.tv_tile_value);
    TextView tvTotalValue = layoutTotal.findViewById(R.id.tv_tile_value);
    tvDayTitle.setText("Today");
    tvWeekTitle.setText("Week");
    tvMonthTitle.setText("Month");
    tvTotalTitle.setText("Total");
    tvDayValue.setText(today);
    tvWeekValue.setText(week);
    tvMonthValue.setText(month);
    tvTotalValue.setText(total);
}

How can I avoid this monstrosity?


Solution

  • You can use the View Binding:

    Add in your build.gradle:

    android {
        ...
        buildFeatures {
            viewBinding true
        }
    }
    

    Create a layout activity_test.xml:

    <androidx.constraintlayout.widget.ConstraintLayout>
    
        <TextView
            android:id="@+id/text1"/>
    
        <TextView
            android:id="@+id/text2"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    Then in your Activity:

    Kotlin

    private lateinit var binding: ActivityTestBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityTestBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
    
        binding.text1.text = "Hello"
        binding.text2.text = "....."
    
    }
    

    Java

    private ActivityTestBinding binding;
    
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        binding = ActivityTestBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);
    
        binding.text1.setText("hello");
    
    }