Android DataBinding - Assigning new values to Model does not update the UI

Viewed 40

I am implementing a simple GraphView in android using a custom view. I have a setter that in the GraphView which takes ArrayList<Integer> as an argument. Later ArrayList<Integer> is used to draw the graph. I am using Android DataBinding to set data array from activity to my custom graph view. I have defined a @BindingAdaptor and I have a Model class, which contains the data array for graph. But setting the data array (calling setGraphPoints() in Activity) does not update the UI. In my case setting a new data array to model does not update the graph. I have used notifyPropertyChanged(BR.statModel) in my setter method of the Model. But it does nothing. If I called activityDataBindings.invalidateAll() it updates the GraphView correctly. Here is the work I have done so far.

Activity.java

public class StatsActivity extends AppCompatActivity {

    private MonthlyStat statModel = new MonthlyStat();
    private ActivityStatsBinding activityStatsBinding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        activityStatsBinding = DataBindingUtil.setContentView(this, R.layout.activity_stats);
        activityStatsBinding.setStatModel(statModel);
        activityStatsBinding.setLifecycleOwner(this);
    }

    //Calling this method to change graph
    private void setGraphPoints() {

        //Generating random set of integer numbers
        ObservableArrayList<Integer> graphPoints = new ObservableArrayList<>();
        for (int i = 0; i < 31; i++) {
            int randomInt = new Random().nextInt(10000);
            graphPoints.add(randomInt);
        }
        statModel.setDataArray(graphPoints);
    }
}

MonthlyStat.java

public class MonthlyStat extends BaseObservable {

    private ObservableArrayList<Integer> graphDataArray;

    public MonthlyStat() {

    }

    public void setDataArray(ObservableArrayList<Integer> graphDataArray) {
        this.graphDataArray = graphDataArray;
        notifyPropertyChanged(BR.statModel);
    }

    public ObservableArrayList<Integer> getDataArray() {
        return graphDataArray;
    }
}

GraphView.java

public class GraphView extends View {

    private ArrayList<Integer> graphPoints;

    public String name;

    public GraphView(Context context) {
        super(context);
    }

    public GraphView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public GraphView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public GraphView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //---- Here Graph Drawing Part ---
        //----
        //----
        //----
        super.onDraw(canvas);
    }

    public void setGraphPoints(ArrayList<Integer> points) {
        graphPoints = points;
        invalidate();
    }
}

GraphViewAdaptor.java

public class GraphViewAdaptor {
    @BindingAdapter("graphPoints")
    public static void setGraphPoints(GraphView view, ObservableArrayList<Integer> graphDataArray) {
        if (graphDataArray == null) {
            view.setGraphPoints(null);
        } else {
            view.setGraphPoints(new ArrayList<>(graphDataArray));
        }
    }
}

activity.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">

    <data>
        <variable
            name="statModel"
            type="com.test.mybudget.model.MonthlyStat" />
    </data>

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="16dp"
            android:layout_marginBottom="8dp" >

         <com.nilupulsandeepa.mybudget.view.GraphView
                android:id="@+id/graphView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:graphPoints="@{statModel.graphDataArray}"/>

    </LinearLayout>

</layout>

Can someone please guide me the correct direction?

2 Answers

Finally found the solution.

My MonthlyStat model should be changed to:

public class MonthlyStat extends BaseObservable {

    @Bindable
    private ArrayList<Integer> graphDataArray;

    public MonthlyStat() {

    }

    public void setGraphDataArray(ArrayList<Integer> graphDataArray) {
        this.graphDataArray = graphDataArray;
        notifyPropertyChanged(BR.graphDataArray);
    }

    public ArrayList<Integer> getGraphDataArray() {
        return graphDataArray;
    }
}

I missed @Bindable annotation and setter and getter method names should be correspond to variable name. Then notifyPropertyChanged should be call inside setter method.

Bro, I think you have mistake you should use statModel.setDataArray(graphPoints);instead monthlyStatModel.setDailyExpensesArray(graphPoints);

Related