How to Use Data-Binding with Fragment

How to use data-binding with Fragment

The data binding implementation must be in the onCreateView method of the fragment, delete any data Binding that exist in your OnCreate method,
your onCreateView should look like this:

public View onCreateView(LayoutInflater inflater, 
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
MartianDataBinding binding = DataBindingUtil.inflate(
inflater, R.layout.martian_data, container, false);
View view = binding.getRoot();
//here data must be an instance of the class MarsDataProvider
binding.setMarsdata(data);
return view;
}

DataBinding+ViewModel in Fragment Android Kotlin

Your ViewModel and Fragment does not have any connection

Do it like this:

BlankFragment:

  private lateinit var vm: MainViewModel

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
vm = activity?.run {
ViewModelProviders.of(this)[MainViewModel::class.java]
} ?: throw Exception("Invalid Activity")
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val binding: FragmentBlankBinding = DataBindingUtil.inflate(inflater,
R.layout.fragment_blank, container, false)
binding.viewmodel = vm//attach your viewModel to xml
return binding.root
}
}

ViewBinding in Fragment

This working fine for me:

private FragmentJavaPracticeBinding binding;

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

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
binding.notesRecyclerView.setVisibility(View.VISIBLE);//this hide/show recyclerview visibility
Log.d("TAG", "hidden: ");
}

Data binding from variable in fragment, android?

First way :

This not direct way which you asked. But you can also do using data class, this is little bit long way but you can add multiple data.

  1. Make data class

    data class Data(var struc: String = "Organization Structure")
  2. Add this in xml

    <data>
    <variable
    name="dataModel"
    type="Data" /> // here data class path of step1
    </data>

    <FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".view.HomeFragment">
    <androidx.appcompat.widget.AppCompatTextView
    android:id="@+id/tvOrganization"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/ivOrganization"
    android:layout_marginTop="20dp"
    android:gravity="center"
    android:text="@{dataModel.struc}" // use like this
    android:textAlignment="center"
    android:textColor="@color/mountmerured"
    android:textSize="15sp" />
    </FrameLayout></layout>
  3. In Activity or fragment

    private fun setData() {
    val data = Data(struc= "Organization")
    bindObject.dataModel = data
    }

Second way :

Or Else direct way is

<data>
<variable
name="struc"
type="String" />
</data>

and from activity/fragment

bindObject.struc = "Organization Structure";

Third way :

Or In your case you need to do this in onCreateView and everything works

binding.data = this;

How to Intialize the Binding Properties in the Fragment to Make Two Way Data Binding Work

I also did this project for my NanoDegree.

Inside my ViewModel I created 3 variables for each EditText:

  • MutableLiveData - to update the value inside the viewModel

  • LiveData to expose value outside viewModel e.g. in a fragment (you won't really need this)

  • Public Variable to monitor value of MutableLiveData and expose this to your xml thus achieving the 2-Way Binding.

Then I and would create a Shared ViewModel to share data between ShoeDetailsFragment and ShoeListingFragment .

Inside the SharedViewModel

I created 3 variables for each EditText (this is just the first 2 Edittexts):

class MySharedViewModel : ViewModel() {
private val _name = MutableLiveData<String>()
val name: LiveData<String>
get() = _name
var edShoeName = ""

private val _size = MutableLiveData<Double>()
val size: LiveData<Double>
get() = _size
var edSize = ""

......}

For the xml I did exactly what you have done but used the 3rd variable for the 2-Way Data Binding:

<EditText
android:id="@+id/shoe_name"
style="@style/login_style"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:hint="@string/shoe_name_string"
android:inputType="text"
android:textSize="30sp"
android:text="@={mySharedViewModel.edShoeName}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title_detail_view" />

<EditText
android:id="@+id/shoe_size"
style="@style/login_style"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/size_string"
android:inputType="number|numberDecimal"
android:textSize="15sp"
android:text="@={mySharedViewModel.edCompany}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/shoe_name" />

I have seen you have included this line of code on your ShoeDetailFragment code:

 binding.saveeButton.setOnClickListener { v: View -> ....}

In my case I did it inside SharedViewModel instead:

fun onSaveButtonClick() {

//check value entered for size and set it to 0 if blank
if (edSize == "") {

edSize = "0"
}



//update MutableLiveData with values read live from the EditText
_name.value = edShoeName
_size.value = edSize.toDouble()


//save shoeObject to the _shoeList MutableLiveData
_shoeList.value?.add(Shoe(edShoeName, edSize.toDouble(), edCompany, edDescription))

}

Using DataBinding I moved the onClick bit to xml:

<Button
android:id="@+id/buttonSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="75dp"
android:layout_marginBottom="75dp"
android:background="@drawable/custom_button_background"
android:onClick="@{()->sharedViewModel.onSaveButtonClick()}"

You can also refer to my project.

Wht when I use view binding for fragment, my app crass without any reason?

In your adapter getView() you are returning binding.root which refers to the fragment layout binding. You should be returning menuRow.root instead.

And you should have an exception in the logcat. Just make sure you don't have any logcat filters or such that hide it.



Related Topics



Leave a reply



Submit