简体   繁体   中英

Data Binding onClick not working

I am getting started for using DataBinding and something is wrong with my onClick.

GameViewModel.java

public void onClickItem(int row, int col){
    Log.d("click","row: "+row+" col: "+col);
}
@BindingAdapter("load_image")
public static void loadImage(ImageView view,int imageId) {
    view.setImageResource(getDrawable(imageId));
}

GameFragment.java

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    //View view=inflater.inflate(R.layout.fragment_game, container, false);
    FragmentGameBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_game, container, false);
    View view = binding.getRoot();
    ButterKnife.bind(this,view);
    binding.setGameViewModel(gameViewModel);
    gameViewModel= ViewModelProviders.of(getActivity()).get(GameViewModel.class);
    gameViewModel.init();
return view;
}

fragment_game.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"

tools:context=".view.GameFragment">

<data>
     <import type="android.support.v4.app.Fragment"/>
    <import type="android.view.View"/>

    <variable
        name="gameViewModel"
        type="harkor.addus.viewmodel.GameViewModel" />
</data>


<android.support.constraint.ConstraintLayout
   (...)>

    <TextView
        (...)>

    <android.support.constraint.ConstraintLayout
        (...)>

        <ImageView
            android:id="@+id/image_puzzle11"
            android:src="@android:color/holo_green_dark"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginEnd="1dp"
            android:layout_marginRight="1dp"
            android:onClick="@{() -> gameViewModel.onClickItem(1,1)}"
            app:load_image="@{0}"
            app:layout_constraintBottom_toTopOf="@+id/image_puzzle21"
            app:layout_constraintDimensionRatio="w,1:1"
            app:layout_constraintEnd_toStartOf="@+id/image_puzzle12"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
(...)

load_image is working, but onClick do nothing... No error in compilation, no crash when button is clicking on device, no result in console...

Please check with below code:

You have written as to call on Click of image as :

 android:onClick="@{() -> gameViewModel.onClickItem(1,1)}"

Try to write as below and check again :

android:onClick="@{(v) -> gameViewModel.onClickItem(1,1)}"

As per the Guidance This is not the way to achieve the Architecture Principles we can work as below as per the MVVM Architecture: 1. Create an Interface 2. Define Interface as handler inside the Layout File as :

<variable
        name="handler"
        type="com.cityguide.interfaces.MustVisitItemListener"></variable>

3.Now we are using this handler to define onclick as :

android:onClick="@{(v) ->handler.onGalleryItemClick(v,currentPosition,photo)}"
  1. Implement the Handler with our java Class or Activity class before bind the Handler with View as below:
 private MustVisitItemListener mItemListener; 

mItemListener = new MustVisitItemListener() { };

5.Set the Interface handler with bind object as below:

mbinding.setHandler(mItemListener);

The easiest way is to set the view model and calling the proper method in the View's onClick from the layout: Your xml:

<data>
    <variable
        name="viewModel"
        type="co.package.MyViewModel" />
</data>

<com.google.android.material.textfield.TextInputEditText
                        android:id="@+id/my_id"
                        android:layout_width="@dimen/full_width"
                        android:layout_height="wrap_content"
                        android:onClick="@{() -> viewModel.doSomething()}" />

But if for any reason you need to call a method from your fragment or activity, the best suggestion is to create an interface to handle the method, implement the method and set it to the layout as follows: Your xml

<data>
    <variable
        name="myHandlers"
        type="co.package.MyHandlersListener" />
</data>

<com.google.android.material.textfield.TextInputEditText
                        android:id="@+id/my_id"
                        android:layout_width="@dimen/full_width"
                        android:layout_height="wrap_content"
                        android:onClick="@{() -> myHandlers.doSomething()}" />

And within your Fragment or Activity you create the interface and then implement it: Your activity/fragment:

/* My Handler Methods */

interface MyHandlersListener {
    fun doSomething()
}

Then implement the listener, taking into consideration that the method something is defined and implemented within your activity/fragment class:

private val myHandlersListener: MyHandlersListener = object : MyHandlersListener {
    override fun doSomething() {
        something()
    }
}

And using databinding, you can set the handler into your layout class (this can be done within the onCreate or onCreateView method depending if you are using and activity or fragment respectively):

myBinding.myHandlers = myHandlersListener

In this way it works perfectly and you follow the guide given by Android's team: https://developer.android.com/topic/libraries/data-binding/expressions#method_references

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM