0

Is it possible to change text of TextView with a method that returns String?

For training purposes i created this ViewModel class, it puts User object into List<User> mUserList and i wonder if i can set first names of this users as text of TextView with a method of ViewMode. I get binding error, can this be fixed using a method that returns String without using @BindingAdapter annotation?

Edit: When i set android:text="@{viewmodel.userList.toString()}" it does not return a binding error but it returns String presentation of User objects. But when i use android:text="@{viewmodel.getUserFirstNames()}" i get a binding error. Why does this happen?

public class UsersViewModel extends ViewModel {

    private List<User> mUserList;

    public List<User> getUserList() {
        if (mUserList == null) {
            mUserList = loadUsers();
        }
        return mUserList;
    }

    /**
     * Dummy Method to fake web service
     *
     * @return list of users
     */
    private List<User> loadUsers() {
    // do something to load users
    List<User> userList = new ArrayList<>();
    User user = new User();
    user.setFirstName("John");
    user.setLastName("Adams");
    userList.add(user);

    user = new User();
    user.setFirstName("Lucy");
    user.setLastName("Adams");
    userList.add(user);

    return userList;

    }


    @NonNull
    private String getUserFirstNames() {
        if (mUserList != null && mUserList.size() > 0) {
            StringBuilder sb = new StringBuilder();
            sb.append("First Names:\n");
            for (User user : mUserList) {
                sb.append(user.getFirstName() + "\n");
            }

            return sb.toString();
        }

        return "empty";
    }
}

In MainActivity i fake to load data with public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        UsersViewModel usersViewModel =
                ViewModelProviders.of(this).get(UsersViewModel.class);
        usersViewModel.getUserList();
        activityMainBinding.setViewmodel(usersViewModel);
    }
}

In layout i wonder if it's possible to set text of TextView with ViewModel class

    <data>

        <variable
            name="viewmodel"
            type="com.example.tutorial1basics.viewmodel.UsersViewModel" />
    </data>

    <android.support.constraint.ConstraintLayout 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"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/tv_users"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{viewmodel.getUserFirstNames()}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />



    </android.support.constraint.ConstraintLayout>
</layout>
Thracian
  • 43,021
  • 16
  • 133
  • 222
  • You want to use ObservableField for it https://developer.android.com/reference/android/databinding/ObservableField – Mayur Patel Jun 21 '18 at 10:49
  • I've just started learning MVVM and i was wondering if it's possible with a method, not with static @BindingAdapter, LiveData, or ObservableField. It's just for educational purposes, i just wonder if it's possible or not? – Thracian Jun 21 '18 at 10:52
  • you can use MVP from this link [this] (https://medium.com/@cervonefrancesco/model-view-presenter-android-guidelines-94970b430ddf) – amin mahmoudi Jun 21 '18 at 10:54
  • Yes its possible. – Mayur Patel Jun 21 '18 at 10:54
  • Thanks. I guess it's not possible. When i set `android:text="@{viewmodel.userList.toString()}"` it does not return a binding error but it returns String presentation of User objects. But when i use `android:text="@{viewmodel.getUserFirstNames()}"` i get a binding error. – Thracian Jun 21 '18 at 10:55
  • You can extend your model with BaseObservable. – Mayur Patel Jun 21 '18 at 10:56
  • @MayurPatel would you minding providing a snipper for it? – Thracian Jun 21 '18 at 10:56
  • @Thracian Yes sure. – Mayur Patel Jun 21 '18 at 10:58
  • @Thracian You may get more from this blog https://medium.com/@fabioCollini/android-data-binding-f9f9d3afc761 – Mayur Patel Jun 21 '18 at 11:01

1 Answers1

1

You want to extends your model with BaseObservable.

Like :

public class Post extends BaseObservable{
    @SerializedName("userId")
    @Expose
    private Integer userId;
    @SerializedName("id")
    @Expose
    private Integer id;
    @SerializedName("title")
    @Expose
    private String title;
    @SerializedName("body")
    @Expose
    private String body;

    @Bindable
    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
        notifyPropertyChanged(BR.userId);
    }

    @Bindable
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
        notifyPropertyChanged(BR.id);
    }

    @Bindable
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
        notifyPropertyChanged(BR.title);
    }

    @Bindable
    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
        notifyPropertyChanged(BR.body);
    }
}
Mayur Patel
  • 2,300
  • 11
  • 30
  • I was actually wondering if it's possible with a class that extends `android.arch.lifecycle.ViewModel`. But as far as i understand data should be some kind of **observable** to be able to set text of with a method or as a field, right? If i extend `android.arch.lifecycle.ViewModel` class then i should use Observable and getter method, right? – Thracian Jun 21 '18 at 11:02
  • My mistake was to set `getUserFirstNames()` method as private. I set it to public and it works now. You can set text of TextView with a method that returns String. The purpose of extending android.arch.lifecycle.ViewModel class is for data to survive device rotation since ViewModel class has it's own life cycle. However you can't notify changes on User without LiveData or ObservableField. – Thracian Jun 21 '18 at 12:00
  • Yes its totally depend on your operation that what kind of work you need. – Mayur Patel Jun 21 '18 at 12:04
  • @Thracian maybe you can help me in this post: https://stackoverflow.com/questions/57285153/how-to-bind-a-view-model-variable-with-custom-class-type – Matan Marciano Jul 31 '19 at 08:03