1

I had an Activity and used ViewBinding there without problems. Not I created a similar Fragment and intend to use ViewBinding there too. Unfortunately I get error messages, altough I followed the steps mentioned at the google develper page about ViewBinding (https://developer.android.com/topic/libraries/view-binding)

Here you can see the Java file:

package com.example.td.barapp;

import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.td.barapp.databinding.ActivitySelectionMenuBinding;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link Menu_Fragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class Menu_Fragment extends Fragment {

    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;



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

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment Menu_Fragment.
     */
    // TODO: Rename and change types and number of parameters
    public static Menu_Fragment newInstance(String param1, String param2) {
        Menu_Fragment fragment = new Menu_Fragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }

        binding.imageButtonCocktailsEn.setOnClickListener(this);
        binding.imageButtonCocktailsAlcfreeEn.setOnClickListener(this);
        binding.imageButtonLongdrinksEn.setOnClickListener(this);
        binding.imageButtonWhiskyEn.setOnClickListener(this);
        binding.imageButtonLiquorEn.setOnClickListener(this);
        binding.imageButtonBeerEn.setOnClickListener(this);
        binding.imageButtonSoftdrinksEn.setOnClickListener(this);
        binding.imageButtonHotDrinksEn.setOnClickListener(this);
    }


    private Menu_FragmentBinding binding;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_menu_, container, false);

        //Include ViewBinding
        binding = Menu_FragmentBinding.inflate(inflater, container, false);
        View view = binding.getRoot();
        return view;

    }
}

I get the error message "Cannot resolve symbol 'Menu_FragmentBinding'" and "Cannot resolve method 'getRoot()'". I do not understand why I get them. Does anyone of you have an idea? I'd appreciate every comment and I would be thankful for your help.

VanessaF
  • 515
  • 11
  • 36
  • What is the name of your layout XML file? – Sourav Bagchi Aug 25 '20 at 14:38
  • Thanks Sourav for your comment. The name of my XML file is "fragment_menu_.xml" – VanessaF Aug 25 '20 at 14:52
  • 1
    Rename it to fragment_menu.xml first then follow my answer. And you don't require `inflater.inflate(R.layout.fragment_menu_, container, false)` in viewbinding – Sourav Bagchi Aug 25 '20 at 14:54
  • There are many technical errors in your code. – Sourav Bagchi Aug 25 '20 at 14:56
  • Thanks Sourav for your comment. Now the Viewbinding seems to be okay. I also noticed that the class has to implement View.OnClickListener. Are there any other mistakes? At least AndroidStudio does not show any other. – VanessaF Aug 25 '20 at 14:59
  • If you are using `newInstance` method to create the fragment object, make the constructor private. Don't access the views in `onCreate` method. Because `onCreateView` method is called after `onCreate` method. So in `onCreate` method, the `binding` object is null. Use `onViewCreated` override method to set the click listeners. – Sourav Bagchi Aug 25 '20 at 15:26
  • Thanks a lot Sourav for the comments and your help. I will try to implement them. – VanessaF Aug 25 '20 at 15:46
  • Thanks Sourav for your comments. Basically much of the code (at least the structure) was created autmatically by Android Studio. So I did not choose to use the newInstnce method. I do not even know what it really does. Further, I do not understand why the parameters ARG_PARAM1, 2 and mParam1, 2 are created and what the purpose is of them. I have never seen them (as I was always working with activities rather than Fragments). Do I really need those parameters and what alternatives exists? I'd appreciate further comments and would be thankful if you could share your experience. – VanessaF Aug 26 '20 at 07:49
  • https://developer.android.com/guide/components/fragments – Sourav Bagchi Aug 26 '20 at 14:50
  • Hi Sourav, I have to say that your advice "make the constructor private" caused many hours for me to search for a mistake because my app was not starting and the error message was that something in the XML file could not be inflated (but it was not specified what). The XML file was okay but your advice caused the big error which caused me about 7 hours yesterday (and two very long StackExchange questions) to find the error. Better do not give this advice any more if your are not sure. – VanessaF Aug 27 '20 at 08:09
  • Do not get me wrong. I of course appreciate your help. But if your are not really experienced in one field then try to make your suggestion a little bit more carefully (at least tell the person that). Even in the autmatically generated Fragment class by Android studio it is told to have the constructor public. Your advice was as misleading as it can get. It gave a strong headache and frustated me and cost me 7 hours to fix it. – VanessaF Aug 27 '20 at 08:13
  • I think you did a big mistake in the Activity class. You didn't use the newInstance method to create Fragment object. You are calling the constructor method to fragment object in the activity class. This newInstance method is generally used to create singleton object. Watch this video- https://www.youtube.com/watch?v=KUk6k865Vgg and you will know why I am telling this. – Sourav Bagchi Aug 27 '20 at 14:39
  • Thanks Sourav for your repy. I do not use Kotlin so I can't understand the video. Anyways it was a big mistake by you to tell me that in the above mentioned class the constructor should be private. This caused an error that was tremendously difficult to find. Still I would like to thank you for your effort altough it caused way more trouble than utility. – VanessaF Aug 27 '20 at 14:43
  • Watch it. Don't afraid the title of the video. In this video, they are talking about Java. You are new in Android development. So I understand your condition. – Sourav Bagchi Aug 27 '20 at 14:52
  • And ViewBinding will retire soon. Jetpack Compose will take its place. So you have to know Kotlin for future Android development. – Sourav Bagchi Aug 27 '20 at 14:56
  • Thanks Sourav for your comment. So why shall I not use the constructor of the fragments to create it but rather the newInstance method? Basically I do not want to do it because I assume that it will be again a huge effort to change that without having significant benefits (at least not for me) – VanessaF Aug 27 '20 at 14:56
  • https://stackoverflow.com/questions/41158396/what-is-difference-between-new-fragment-and-fragment-getinstance-in-andr – Sourav Bagchi Aug 27 '20 at 14:57
  • Suppose you have multiple fragments. You have to pass data from one fragment to another fragment. How will you do that? That's why newInstance method is required. It is a very good practice. https://stackoverflow.com/questions/9245408/best-practice-for-instantiating-a-new-android-fragment – Sourav Bagchi Aug 27 '20 at 15:00
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/220564/discussion-between-sourav-bagchi-and-vanessaf). – Sourav Bagchi Aug 27 '20 at 15:03
  • Might be possible that you are using a very old approach (posted in the chat)? – VanessaF Aug 28 '20 at 07:51

1 Answers1

1

First of all, don't use trailing underscore in the layout file name. Remove the trailing underscore from fragment_menu_

A binding class is generated for each layout file. By default, the name of the class is based on the name of the layout file, converting it to Pascal case and adding the Binding suffix to it. The above layout filename is activity_main.xml so the corresponding generated class is ActivityMainBinding.

So if the name of your layout file is frargemnt_menu.xml, so the corresponding generated class is FragmentMenuBinding

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //Inflate using viewbinding
        binding = FragmentMenuBinding.inflate(inflater, container, false);
        return binding.getRoot();

    }
Sourav Bagchi
  • 656
  • 7
  • 13
  • Thanks Sourav for your answer and help. The Viewbinding seems to work. – VanessaF Aug 25 '20 at 15:02
  • Hi Sourav, I can't find the generated Binding classes in my folders. There is one Folder with classes like: DataBindingComponent, DataBinderMapperImpl and DataBinderMapperImpl, but I can't the generated binding classes anywhere (e.g. the FragmentMenuBinding). Do you have an idea where they can be found? I'd appreciate further comments. – VanessaF Aug 26 '20 at 07:44
  • Actually I never searched for it. And they are generated automatically. So you can't modify them – Sourav Bagchi Aug 26 '20 at 14:51