Search code examples
android-databindingandroid-livedataandroid-mvvmmutablelivedata

LiveData update values when field of object change


Today I'm trying to use a LiveData (MutableLiveData) object to have some dynamics values. (in MVVM pattern)

I used a model object like this:

public class Object {
    private String name;
    private float internalvalue;
    private float in1;
    private float out1;
    private float out2;

    public Object(String name, float internalvalue){
        this.name = name;
        this.internalvalue = internalvalue;
    }

    public float getOut1(){
        return this.out1;
    }

    public float getOut2(){
        return this.out2;
    }

    public void setIn1(float in1){
        this.in1 = in1;

    }

    private void performSomething(float internalvalue, float in1){
        SubClassSingleton.performSomething(internalvalue, in1, new SubClassSingletonListener() {
            @Override
            public void onSuccess(float out1, float out2){
                this.out1 = out1;
                this.out2 = out2;
            }
        });
    }
}

I use a ViewModel like this:

public class MainViewModel {
    public MutableLiveData<Object> obj;

    public MainViewModel(){
        this.obj = new MutableLiveData<>();
        this.obj.postValue(new Object("Name", 50.0f);
    }
}

In MainFragment:

public class MainFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        MainViewModel viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
        MainFragmentBinding binding = MainFragmentBinding.inflate(getLayoutInflater());
        binding.setViewModel(viewModel);
        binding.setLifecycleOwner(this);
        return binding.getRoot();
    }
}

And in View:

<layout ...
    <data>
        <variable
            name="viewModel"
            type="app.example.MainViewModel"/>
    </data>
    <LinearLayout
        ...>
        <EditText
            android:text="@={viewModel.obj.in1}"
            .../>
        <TextView
            android:text="@{viewModel.obj.out1}"
            .../>
        <TextView
            android:text="@{viewModel.obj.out2}"
            .../>
    </LinearLayout>
</layout>

I'd like to update my view when the values (out1, out2) of my model are updated (when the calculation is performed).

How can I do this ?


Solution

  • Try this:

    You need to make your model class extend BaseObservable.

    public class Object extends BaseObservable {
        private String name;
        private float internalvalue;
        private float in1;
        private float out1;
        private float out2;
    
        public Object(String name, float internalvalue) {
            this.name = name;
            this.internalvalue = internalvalue;
        }
    
        public float getOut1() {
            return this.out1;
        }
    
        public void setOut1(float out1) {
            this.out1 = out1;
            notifyChange();
        }
    
        public float getOut2() {
            return this.out2;
        }
    
        public void setOut2(float out2) {
            this.out2 = out2;
            notifyChange();
        }
    
        public void setIn1(float in1) {
            this.in1 = in1;
        }
    
        private void performSomething(float internalvalue, float in1) {
            SubClassSingleton.performSomething(internalvalue, in1, new SubClassSingletonListener() {
                @Override
                public void onSuccess(float out1, float out2) {
                    setOut1(out1);
                    setOut2(out2);
                }
            });
        }
    }
    

    And in View, you cannot bind float directly to view. It has to be string, so bind like this:

    <layout ...
        <data>
            <variable
                name="viewModel"
                type="app.example.MainViewModel"/>
        </data>
        <LinearLayout
            ...>
            <EditText
                android:text='@={""+viewModel.obj.in1}'
                .../>
            <TextView
                android:text='@{""+viewModel.obj.out1}'
                .../>
            <TextView
                android:text='@{""+viewModel.obj.out2}'
                .../>
        </LinearLayout>
    </layout>