Хорошо ли использовать подход ViewModel в представлении одного элемента внутри адаптера представления переработчика? - PullRequest
3 голосов
/ 01 июля 2019

Я обычно использую компоненты архитектуры MVVM в своем приложении, но заметил, что может создать новый ViewModel, специфичный для представления отдельного элемента внутри адаптера с представлением переработчика.

так что мой вопрос это хорошая практика? создать viewmodel для одного элемента? я уже создаю модель представления для фрагмента, но почему для адаптера и представления одного элемента ?! будет создано 2 модели вида! спасибо за помощь.

Давайте посмотрим:

AllShopsItem.java

работает как модель предмета

public class AllShopsItem {

private String image;
private String name;
private float rate;
private String details;
private String miniCharge;
private String shipping;

public AllShopsItem(String image, String name, float rate, String details, String miniCharge, String shipping) {
    this.image = image;
    this.name = name;
    this.rate = rate;
    this.details = details;
    this.miniCharge = miniCharge;
    this.shipping = shipping;
}

public String getImage() {
    return image;
}

public void setImage(String image) {
    this.image = image;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public float getRate() {
    return rate;
}

public void setRate(float rate) {
    this.rate = rate;
}

public String getDetails() {
    return details;
}

public void setDetails(String details) {
    this.details = details;
}

public String getMiniCharge() {
    return miniCharge;
}

public void setMiniCharge(String miniCharge) {
    this.miniCharge = miniCharge;
}

public String getShipping() {
    return shipping;
}

public void setShipping(String shipping) {
    this.shipping = shipping;
}
}//end model class

SingleItemAllShopsViewModel.java

посмотреть модель изделия

public class SingleItemAllShopsViewModel extends BaseViewModel {
private AllShopsItem allShopsItem;

public SingleItemAllShopsViewModel(AllShopsItem allShopsItem) {
    this.allShopsItem = allShopsItem;
}

public void setUp() {
    // perform set up tasks, such as adding listeners
}

public void disposeListeners() {
    // perform tear such as removing listeners
}

@Bindable
public AllShopsItem getAllShopsItem() {
    return allShopsItem;
}

@BindingAdapter({"imageUrl"})
public static void setImageUrl(ImageView view, String imagePath){
    Timber.d(imagePath);
    ConnectionHelper.loadImage(view,  imagePath);
}

}//end viewmodel

AllShopsViewHolder.java

держатель держателя

public class AllShopsViewHolder extends RecyclerView.ViewHolder {
private SingleItemAllShopsBinding binding;

public AllShopsViewHolder(@NonNull View itemView) {
    super(itemView);
    bind();
}

public void bind() {
    if (binding == null) {
        binding = DataBindingUtil.bind(itemView);
    }
}

public void unbind() {
    if (binding != null) {
        binding.unbind(); // Don't forget to unbind
    }
}

public void setViewModel(SingleItemAllShopsViewModel viewModel) {
    if (binding != null) {
        binding.setViewModelBinding(viewModel);
    }
}

}//end view holder

AllShopsAdapter.java

адаптер класса

public class AllShopsAdapter extends RecyclerView.Adapter<AllShopsViewHolder> {
private ArrayList<AllShopsItem> dataList;

public void setNewDataList(ArrayList<AllShopsItem> dataList) {
    this.dataList = dataList;
    notifyDataSetChanged();
}

public void updateDataList(ArrayList<AllShopsItem> dataList) {
    this.dataList.clear();
    this.dataList.addAll(dataList);
    notifyDataSetChanged();
}

@Override
public void onViewAttachedToWindow(@NonNull AllShopsViewHolder holder) {
    super.onViewAttachedToWindow(holder);
    Timber.d("onViewAttachedToWindow");
    holder.bind();
}

@Override
public void onViewDetachedFromWindow(@NonNull AllShopsViewHolder holder) {
    super.onViewDetachedFromWindow(holder);
    Timber.d("onViewDetachedFromWindow");
    holder.unbind();
}

@NonNull
@Override
public AllShopsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_item_all_shops,
            new FrameLayout(parent.getContext()), false);
    return new AllShopsViewHolder(itemView);
}

@Override
public void onBindViewHolder(@NonNull AllShopsViewHolder holder, int position) {
    SingleItemAllShopsViewModel allShopsViewModel = new SingleItemAllShopsViewModel(getCurrentItem(position));
    holder.setViewModel(allShopsViewModel);
}

public AllShopsItem getCurrentItem(int pos) {
    return dataList.get(pos);
}

@Override
public int getItemCount() {
    return dataList != null && !dataList.isEmpty() ? dataList.size() : 0;
}
}//end adapter

single_item_all_shops.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="viewModelBinding"


type="grand.shopness.view.adapter.itemviewmodel.SingleItemAllShopsViewModel" />
</data>

<androidx.cardview.widget.CardView
    android:id="@+id/cv_root"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:id="@+id/rl_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingStart="@dimen/dp16w"
        android:paddingEnd="@dimen/dp16w"
        android:paddingTop="@dimen/dp8h"
        android:paddingBottom="@dimen/dp8h">

        <androidx.cardview.widget.CardView
            android:id="@+id/cv_image"
            android:layout_width="80dp"
            android:layout_height="80dp"
            app:cardElevation="8dp"
            android:layout_centerVertical="true"
            android:layout_alignParentStart="true">
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:src="@drawable/slider_img"
            android:scaleType="fitXY"
            tools:ignore="ContentDescription"
            app:imageUrl="@{viewModelBinding.allShopsItem.image}"/>
        </androidx.cardview.widget.CardView>


        <RelativeLayout
            android:id="@+id/rl_info"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_toEndOf="@id/cv_image"
            android:paddingStart="@dimen/dp4w"
            android:paddingEnd="@dimen/dp4w"
            android:layout_toStartOf="@id/rl_prices"
            android:layout_centerVertical="true">

            <TextView
                android:id="@+id/tv_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:fontFamily="@font/raleway_medium"
                tools:text="Shop name"
                android:textColor="@android:color/black"
                android:textSize="14sp"
                android:textStyle="bold"
                android:text="@{viewModelBinding.allShopsItem.name}"/>

            <RatingBar
                android:id="@+id/ratingBar"
                style="@style/RatingBarStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/tv_name"
                android:indeterminate="false"
                android:numStars="5"
                android:layout_marginTop="@dimen/dp2h"
                android:layout_alignParentStart="true"
                tools:rating="5"
                android:rating="@{viewModelBinding.allShopsItem.rate}"/>

            <TextView
                android:id="@+id/tv_details"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:fontFamily="@font/raleway_medium"
                tools:text="detailssssssssssssssasdasdasdsadasdasdasdasdadasdasdasdasdasdasdasdasdsssss"
                android:textColor="@android:color/black"
                android:layout_alignParentStart="true"
                android:layout_below="@id/ratingBar"
                android:maxLines="2"
                android:ellipsize="end"
                android:text="@{viewModelBinding.allShopsItem.details}"/>

        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/rl_prices"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_centerVertical="true"
            android:layout_marginStart="@dimen/dp4w">

            <TextView
                android:id="@+id/tv_mini_charge_static"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:fontFamily="@font/raleway_medium"
                android:text="@string/mini_charge"
                android:textColor="@android:color/black"
                android:layout_centerHorizontal="true"
                android:layout_alignParentTop="true" />

            <TextView
                android:id="@+id/tv_mini_charge"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{viewModelBinding.allShopsItem.miniCharge}"
                tools:text="150"
                android:textColor="@android:color/black"
                android:layout_centerHorizontal="true"
                android:layout_below="@id/tv_mini_charge_static"/>

            <TextView
                android:id="@+id/tv_shipping_static"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:fontFamily="@font/raleway_medium"
                android:text="@string/shipping"
                android:textColor="@android:color/black"
                android:layout_centerHorizontal="true"
                android:layout_below="@id/tv_mini_charge"/>

            <TextView
                android:id="@+id/tv_shipping"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                tools:text="10"
                android:text="@{viewModelBinding.allShopsItem.shipping}"
                android:textColor="@android:color/black"
                android:layout_centerHorizontal="true"
                android:layout_below="@id/tv_shipping_static"/>

        </RelativeLayout>
    </RelativeLayout>
</androidx.cardview.widget.CardView>
</layout>

вот так это будет выглядеть:

enter image description here

Ответы [ 2 ]

1 голос
/ 02 июля 2019

Я думаю, что это плохая идея.причина в том, что viewModel создан для работы с компонентом, поддерживающим жизненный цикл, таким как Activity, Fragment, но не для этого вида использования

Официальная документация гласит, что

ViewModel - класс, отвечающий за подготовкуи управление данными для Действия или Фрагмента Официальный документ

1 голос
/ 01 июля 2019

Не думаю, что если честно, это выглядит довольно странно. Да, viewmodel предназначен для управления данными, связанными с пользовательским интерфейсом, и позволяет данным выживать после изменений конфигурации, но, делая это, вы просто добавляете некоторую сложность к вашему адаптеру без веской причины. Ваша view-модель предназначена для того, чтобы помочь вам обрабатывать данные об активности / фрагменте, которые включают в себя данные вашего повторного просмотра, вот и все, просто убедитесь, что ваша view-модель должным образом сохраняет состояние просмотра вашего переработчика и поддерживает простой адаптер

...