Android View Binding overview and basic use

foreword

Friends who use the kotlin language for Android development must be familiar with the Kotlin-android-extensions plug-in. This plug-in can help us save the writing of findviewbyid(). Without adding other code, we can directly use the control id defined in xml to directly call the control in the kotlin code, and the rest of the work is automatically done by the plug-in.

This plug-in can be said to be very convenient in Android development, especially when complex pages contain a large number of Views, it can save us a lot of trivial code writing. But since Android Studio 4.1 , whenever we create a new project again, the compiler will no longer help us automatically introduce this control.

After discovering this problem, I found it very strange, especially the previous compiler used to introduce this plugin in newly created projects. So I checked the official google instructions and got the following results:

Google reminds us that the Kotlin-android-extensions plug-in has been discarded. In later versions, it is recommended to use View Binding for view binding to replace the extensions plug-in.

Then this article will give a brief description of the use of View Binding .

1. Configuration

Before using View Binding, you first need to determine the Android Studio version you are currently using . Only Android Studio after 3.6 can support View Binding.

The official documentation states:

View binding View binding is available in Android Studio 3.6 Canary 11 and later .

After confirming that the compiler version is available, we can use View Binding. First, we need to configure and enable viewbinding in the build.gradle file. The configuration code is as follows:

android {
        ...
        viewBinding {
            enabled = true
        }
    }

2. Document Generation Instructions

After the above configuration, the current module starts the viewBinding function, and Android Studio will automatically generate the corresponding Binding class for each layout file we write.

The naming rule is to rename the camel case of the xml file name + Binding ,

Its location is in the **build/generated/data_binding_base_class_sorce_out/debug/out/com.../databinding/** folder.

Examples are as follows:

If we define a activity_single_main.xmllayout, its corresponding file name ActivitySingleMainBindingand its location are as follows:

viewbinding file location map.jpg

After enabling the ViewBinding function, Android Studio will generate a corresponding Binding class for each layout file we write. If you do not need to generate a Binding file for the layout, you can tools:viewBindingIgnore="true"add attributes to the root view of the corresponding layout file, as follows:

<LinearLayout
            ...
            tools:viewBindingIgnore="true" >
        ...
</LinearLayout>

Next, briefly explain the use of Viewbinding in Activity and Fragment.

3. Basic use

1. Use in Activity

It is relatively simple to use in Activity, we onCreate()execute the following code in the method:

    private ActivityMainLibJavaBinding binding;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        binding = ActivityMainLibJavaBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);
    }

That is, the following steps:

  1. Call the static inflate() method contained in the bound class
  2. Call the getRoot() method to get the View
  3. Pass View into setContentView()to make it the active view on the screen.

The kotlin code is similar (the processing of the two languages ​​is basically the same, and the Java code will be used to illustrate) :

    private lateinit var viewBinding: ActivitySingleMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewBinding = ActivitySingleMainBinding.inflate(layoutInflater)
        setContentView(viewBinding.root)
    }

After the above steps, we can use the instance of the binding class binding.XXto refer to the view, as follows:

        getSupportFragmentManager().beginTransaction().replace(binding.content.getId(),new Test1Fragment()).commitAllowingStateLoss();

Simple encapsulation in BaseActivity is convenient to use, as follows:

public abstract class BaseActivity<VB extends ViewBinding> extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        VB binding = getBinding();
        setContentView(binding.getRoot());
    }

     abstract protected VB getBinding();
}

Implement the method in the Activity getBinding(), and then you can use getBinding().XXthe reference layout control:

public class MainLibJavaActivity extends BaseActivity<ActivityMainLibJavaBinding> {

    @Override
    protected ActivityMainLibJavaBinding getBinding() {
        return ActivityMainLibJavaBinding.inflate(getLayoutInflater());
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportFragmentManager().beginTransaction().replace(getBinding().content.getId(),new Test1Fragment()).commitAllowingStateLoss();
    }
}

2. Use in Fragment

To use in Fragment, you need to onCreateView()perform the following binding in the method of Fragment, and remove the binding when the view is destroyed. The code is as follows:

public class Test1Fragment extends BaseFragment {

    private FragmentTest1Binding binding;

    public Test1Fragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        binding = FragmentTest1Binding.inflate(inflater, container, false);
        View view = binding.getRoot();
        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }

}
  1. Calls a static method contained in the generated binding class inflate(), which creates an instance of the binding class for the Fragment to use.
  2. getRoot()Obtain a reference to the actual graph by calling the method
  3. onCreateView()The return value is set to the root view, making it the active view on the screen.
  4. At the same time, we also need to destroy the current Binding reference when the Fragment's view is destroyed.

After the above steps, we can use the instance of the binding class to refer to the view. The format is similar to that used in Activity. The binding.XXformat is as follows:

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        binding.tvTest1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(), "这是一条测试数据", Toast.LENGTH_SHORT).show();
            }
        });
    }

Simple encapsulation in BaseFragment is easy to use, as follows:

public abstract class BaseFragment<VB extends ViewBinding> extends Fragment {
    protected VB binding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = initViewBinding(inflater, container, savedInstanceState);
        return binding.getRoot();
    }

    abstract protected VB initViewBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState);

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
}

initViewBindingThe instance reference can be called by implementing the method in Fragment . The sample code is as follows:

public class Test1Fragment extends BaseFragment<FragmentTest1Binding> {

    public Test1Fragment() {
        // Required empty public constructor
    }

    @Override
    protected FragmentTest1Binding initViewBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return FragmentTest1Binding.inflate(inflater,container,false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        binding.tvTest1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(), "这是一条测试数据", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

Fourth, the difference with findViewById

findViewByIdView binding has some significant advantages over using :

  • Null safety : Since view binding creates a direct reference to the view, there is no risk of a Null pointer exception being thrown due to an invalid view ID. Also, if the view only appears in certain configurations of the layout, the field containing its reference in the binding class is @Nullablemarked .
  • Type Safety : Fields in each bound class have types that match the views they reference in the XML file. This means that there is no risk of class conversion exceptions.

These differences mean that incompatibilities between layout and code will cause builds to fail at compile time rather than runtime.

Summarize

After the Kotlin-android-extensions plug-in has been abandoned, we can use View Binding to replace the extensions plug-in function, simplify the development code, and support both Java and kotlin. The two languages ​​are basically the same. This article uses Java code as an example. .

reference article

Official Google Docs

Guess you like

Origin blog.csdn.net/cat_is_so_cute/article/details/121200507