Vlado Pandžić
Vlado Pandžić

Reputation: 5048

android databinding inside recyclerview

I have checkboxes, edittexts and other inputs inside my recyclerview. I successfully implemented databinding whick means data is populated from the data I get from web service. When I change some input foe example change value 104 to 107 and scroll down (so that EditText) is now longer in viewport and scroll back I get value 104 again. It seems RecyclerView is caching old value and my that databinding library is not updating model.(Yes I'm using using Bindable attribute and other necessary stuff) and I also use executePendingBindings method inside adapter.

This is my RecyclerView adapter:

public class SimpleAttributesAdapter extends RecyclerView.Adapter<SimpleAttributesAdapter.AttributesViewHolder> {


private final Context context;
private final List<Attribut> allAttributes;

public SimpleAttributesAdapter(Context context,List<Attribut> _allAttributes)
{
    this.context=context;
    this.allAttributes=_allAttributes;
}


@Override
public AttributesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater=LayoutInflater.from(context);
    RecyclerViewAttributesChildOneRowBinding binding= DataBindingUtil.inflate(inflater, R.layout.recycler_view_attributes_child_one_row, parent, false);
    MyHandlers handlers = new MyHandlers();
    binding.setHandlers(handlers);
    return new AttributesViewHolder(binding);
}

@Override
public void onBindViewHolder(AttributesViewHolder holder, int position) {
    RecyclerViewAttributesChildOneRowBinding binding=holder.getViewDataBinding();
    binding.setAttribute(allAttributes.get(position));
   holder.getViewDataBinding().executePendingBindings();

}

@Override
public int getItemCount() {
    return allAttributes.size();
}

public  class AttributesViewHolder extends RecyclerView.ViewHolder {

       private RecyclerViewAttributesChildOneRowBinding binding;

    public AttributesViewHolder(RecyclerViewAttributesChildOneRowBinding viewDataBinding)
    {
        super(viewDataBinding.getRoot());
        binding=viewDataBinding;
      binding.executePendingBindings();
    }
    public RecyclerViewAttributesChildOneRowBinding getViewDataBinding() {
        return binding;
    }
}
}

This is my layout file:

 < ?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
  <data>
    <import type="com.adriagate.adriagateonlineandroid.models.Attribut"/>
    <variable
       name="attribute"
      type="com.adriagate.adriagateonlineandroid.models.Attribut" />
   <import type="android.view.View"/>
   <variable name="handlers"            
       type="com.adriagate.adriagateonlineandroid.MyHandlers"/>

 </data>

<LinearLayout
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@{attribute.Question}"/>

<EditText
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:text="@{attribute.Answer}"
    android:inputType="number"
    bind:visibility="@{attribute.isNumber ? View.VISIBLE : View.GONE}"
    />

<EditText
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:text="@{attribute.Answer}"
    android:inputType="text"
    bind:visibility="@{attribute.isString ? View.VISIBLE : View.GONE}"
    />
<android.support.v7.widget.AppCompatSpinner
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    bind:adriagateentries="@{attribute.Choices}"
    bind:visibility="@{attribute.isSelect ? View.VISIBLE : View.GONE}"
    bind:selectedId="@{attribute.ChoiceId}"
    style="@style/Widget.AppCompat.Spinner.Underlined"
    />
 <CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
bind:checked="@{attribute.Selected}"
bind:visibility="@{attribute.isBool ? View.VISIBLE : View.GONE}"/>


  </LinearLayout>
  </layout>

This is my model:

public class Attribute extends BaseObservable {

@Bindable
public String getAnswer() {
    return Answer;
}

public void setAnswer(String answer) {
    Answer = answer;
    notifyPropertyChanged(BR.answer);
}



public List<Choice> getChoices() {
    return Choices;
}

public void setChoices(List<Choice> choices) {
    Choices = choices;
}



public int getType() {
    return Type;
}

public void setTypeype(int attributeType) {
    Type = attributeType;
}

@Bindable
public String getChoiceId() {
    return ChoiceId;
}

public void setChoiceId(String choiceId) {
    ChoiceId = choiceId;
   notifyPropertyChanged(BR.choiceId);
}

@Bindable
private String Answer; //tipovi 1


@Bindable
private String ChoiceId; //tipovi 1

private List<Choice> Choices; //za tip 3

private int Type;

public boolean isNumber() {
    return this.isNumber = this.getType()==1;
}
private boolean isNumber ;

public boolean isSelect() {
    return this.isSelect = this.getType()==3;
}
private boolean isSelect ;

public boolean isString() {
    return this.isString = this.getType()==2;
}
private boolean isString ;

private boolean isBool ;
public boolean isBool() {
    return this.isBool = this.getType()==5;
}

private boolean isChecked;
public boolean isChecked() {
    return this.Answer =="D";
}

}

Upvotes: 2

Views: 2886

Answers (1)

2LiKoO
2LiKoO

Reputation: 26

With Android Studio 2.1, you can enable two-way data binding by using the "@={}" syntax in your layout.

For instance, try replacing :

@{attribute.Answer}

by :

@={attribute.Answer}

in your layout file.

For more reference, you can check this tutorial : https://halfthought.wordpress.com/2016/03/23/2-way-data-binding-on-android/

Upvotes: 1

Related Questions