Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Data binding issue Binding adapter call twice

I have simple imageview in my layout and I have a api which gives me a image url. I integrate Data binding in my layout. Now after parsing the api I'm setting the model through this line binding.setUserinfo(memberObj.getMemberdata());

Now I have also a binding adapter where imgurl code is written. Now the custom binding adapter calls twice when activity start and after parsing the api.

Now i want to notify the UI after api has been successfully parsed.

Here is my code of xml activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    <data class="MainBinding">
        <variable
            name="userinfo"
            type="com.myapplication.retrofit.pojo.ImgTest"/>
    </data>
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.myapplication.retrofit.MainActivity">
    <ImageView
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:id="@+id/imageView"
        app:image_url="@{userinfo.imgUrl}"
        />
</RelativeLayout>
</layout>

Here is my Pojo: ImgTest.java

public class ImgTest extends BaseObservable {

    String imgUrl;
    @Bindable
    public String getImgUrl() {
        return imgUrl;
    }

    public void setImgUrl(String imgUrl) {
        this.imgUrl = imgUrl;
        notifyPropertyChanged(BR.imgUrl);
    }
}

Here is my CustomBinder.java

public class CustomBinders {
    private static final String TAG = "CustomBinders";
    @BindingAdapter({"image_url"})
    public static void loadImageWithOUtProgressBar(ImageView view, String imageUrl){

        Log.d(TAG, "before loadImageWithOUtProgressBar: "+imageUrl);
        Log.d(TAG, "after loadImageWithOUtProgressBar: "+imageUrl);
        Picasso.with(view.getContext())
                .load(imageUrl)
                .into(view);
    }

}

Here is MainActivity.java

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    RestManager mManager;
    MainBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        mManager = new RestManager();
        Call<ResponseBody> getUserInfo = mManager.getService().getUserInfo("25","sell");
        getUserInfo.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                int sc = response.code();
                Log.d(TAG, "onResponse: "+sc);

                if(response.isSuccessful())
                {
                    ImgTest img = new ImgTest();
                        try {
                            String res = response.body().string();
                            JSONObject jobj = new JSONObject(res);             
                            JSONObject obj = jobj.getJSONObject("memberdata");                           
                            String imgUrl = "";
                            imgUrl = obj.getString("prifile_picture");
                            img.setImgUrl(imgUrl);
                            binding.setUserinfo(img);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {

            }
        });
    }
}

Please let know how to solve this issue. Thanks in advance.

like image 573
Subho Avatar asked Sep 07 '16 11:09

Subho


People also ask

What is binding adapter in data binding Android?

Binding adapters are responsible for making the appropriate framework calls to set values. One example is setting a property value like calling the setText() method. Another example is setting an event listener like calling the setOnClickListener() method.

What is 2 way data binding Android?

Two-way Data Binding is a technique of binding your objects to your XML layouts so that the layout can send data to your binding object. This is compared to a “traditional” or “one-way” Data Binding setup, where data would only move from your binding object to the layout.

What is inverse binding adapter in android?

InverseBindingAdapter is associated with a method used to retrieve the value for a View when setting values gathered from the View.


1 Answers

As Ravi says in the comments, it is working as intended. After you create the initial binding, the values should be set to the values as they are. If you haven't set anything then they will be set to null.

You can change the behavior by explicitly telling the binding to not bind. Add an OnRebindCallback to the binding:

private OnRebindCallback<ActivityMainBinding> delayRebindCallback = 
        new OnRebindCallback<ActivityMainBinding>() {
    @Override
    public boolean onPreBind(ActivityMainBinding binding) {
        return false;
    }
};

// ... and then after creating the binding ...
binding.addOnRebindCallback(delayRebindCallback);

In your onResponse (assuming it is on the UI thread):

binding.removeOnRebindCallback(delayRebindCallback);
binding.setUserinfo(img);
binding.executePendingBindings();

If it isn't on the UI thread, you will have to post an executable to run the binding.executePendingBindings() on the UI thread.

like image 104
George Mount Avatar answered Sep 27 '22 16:09

George Mount