Как обновить 1 адаптер представления переработчика из 2 моделей просмотра? - PullRequest
1 голос
/ 05 ноября 2019

У меня есть 2 модели представления, которые наблюдают за 2 таблицами в комнате, каждая из которых выдает живые данные, они должны обновлять мое представление переработчика при изменении значения. Мой адаптер оборудован для работы с несколькими моделями и держателями видов, но я не уверен, как обновить адаптер видов рециркулятора новыми данными, не перезаписывая текущие данные и не дублируя какие-либо идеи.

Итак, мой адаптер берет список Visitable (шаблон Visitable). У меня есть 2 объекта, которые реализуют этот интерфейс, интерфейс имеет тип, так что я могу сказать, какой держатель представления он хочет, и я обновляю представление рециркулятора, используя diff utilsЭто выглядит так:

public class CardAdapter extends RecyclerView.Adapter<BaseViewHolder> {

private final List<Visitable> elements;
private final TypeFactory typeFactory;
private final ItemTouchListener onItemTouchListener;
private final Context context;
private String cardType;
private final String layoutIdentifier;
private static final String TAG = "Adptr-Card";
private String CARD_CLICK_UPDATE = "card_click_update";
private final String[] imageFilePathNames;
private RequestManager glide;


public CardAdapter(List<Visitable> elements, TypeFactory typeFactory, ItemTouchListener onItemTouchListener,
                   Context context,
                   String cardType, String layoutIdentifier, RequestManager glide) {
    this.glide = glide;
    this.elements = elements;
    this.typeFactory = typeFactory;
    this.onItemTouchListener = onItemTouchListener;
    this.context = context;
    this.cardType = cardType;
    this.layoutIdentifier = layoutIdentifier;
    this.imageFilePathNames = context.getResources().getStringArray(R.array.image_set_names);
}

@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View contactView = LayoutInflater.from(context).inflate(viewType, parent, false);
    return typeFactory.createViewHolder(contactView, viewType, onItemTouchListener, glide, cardType);

}

@Override
public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
    holder.bind(elements.get(position), position);
}

@Override
public int getItemViewType(int position) {
    return elements.get(position).type(typeFactory);
}

public void setCardType(String cardType) {
    this.cardType = cardType;
    notifyDataSetChanged();

}

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

public List<Visitable> getList() {
    return elements;
}

public List<Sentence> getSentencesList() {
    ArrayList<Sentence> sentences = new ArrayList<>();
    for (Visitable visitable : elements) {
        if (visitable.type(typeFactory) == CardViewHolder.LAYOUT) {
            sentences.add((Sentence) visitable);
        }
    }
    return sentences;
}

public Visitable getItem(int position) {
    if (position > 0 && position < elements.size()) {
        return elements.get(position);
    }
    return elements.get(0);
}


class CalculateDiffUtils extends AsyncTask<Void, Void, DiffResult> {

    private final List<Visitable> oldCardList;
    private final List<Visitable> newCardList;

    CalculateDiffUtils(List<Visitable> oldCardList, List<Visitable> newCardList) {
        this.oldCardList = oldCardList;
        this.newCardList = newCardList;
    }

    @Override
    protected DiffUtil.DiffResult doInBackground(Void... params) {
        return DiffUtil.calculateDiff(new VisitableDiffUtils(oldCardList, newCardList, typeFactory));
    }

    @Override
    protected void onPostExecute(DiffUtil.DiffResult diffResult) {
        super.onPostExecute(diffResult);
        dispatchUpdates(diffResult, newCardList);

    }
}

private void dispatchUpdates(DiffUtil.DiffResult diffResult, List<Visitable> newCardList) {
    this.elements.clear();
    this.elements.addAll(newCardList);
    diffResult.dispatchUpdatesTo(this);
}

public void refreshDiffUtilsList(List<Visitable> sentences) {
    new CalculateDiffUtils(elements, sentences).execute();
}



public void removeItem(int position) {
    elements.remove(position);
    notifyItemRemoved(position);
}


public void addCard(Sentence sentence) {
    elements.add(getItemCount(), sentence);
    notifyItemInserted(getItemCount());
}

public void addGroup(GroupsWithSentences sentence) {
    elements.add(getItemCount(), sentence);
    notifyItemInserted(getItemCount());
}


public void updateCardClick(int position) {
    notifyItemChanged(position, CARD_CLICK_UPDATE);
}


public void refreshList(List<Visitable> newElements) {
    ArrayList<Visitable> elementArrayList = new ArrayList<>(newElements);
    elements.clear();
    elements.addAll(elementArrayList);
    notifyDataSetChanged();
}

}

Мои модели двух представлений располагаются фрагментом, они наблюдают некоторые данные из моей базы данных Room и обновляются, когда происходят изменения, но это означает, что я когда-либо получу данные только от одногоиз моделей представлений, я думаю, мне нужен способ объединить эти модели представлений, возможно, используя какие-то посреднические живые данные, вот мои две модели представлений (я для краткости удалил материал, они оба инициированы с использованием фабрик)

МОДЕЛЬ ВИДА ГРУППЫ

public class GroupViewModel extends ViewModel {

private final GroupRepository groupRepository;
private final LiveData<List<GroupsWithSentences>> groups;

public GroupViewModel(@NonNull Application application, String[] cardArgs) {
    groupRepository = new GroupRepository(application);
    groups = groupRepository.getGroupsByWordDescriptionAndWordType(cardArgs[0],cardArgs[1]);
}

public LiveData<List<GroupsWithSentences>> getGroups() {
    return groups;
}
}

МОДЕЛЬ ВИДА ОТПРАВЛЕНИЯ

public class CardViewModel extends ViewModel {

private final SentenceRepository sentenceRepository;
private final LiveData<List<Sentence>> cards;
private static final String TAG = "view_model";

public CardViewModel(@NonNull Application application , int clicks){
    sentenceRepository = new SentenceRepository(application);
    search = new MutableLiveData<>();
    cardArgs = new MutableLiveData<>();
    cards = Transformations.switchMap(search, mySearch -> sentenceRepository.searchLiveCardListByWordTypeAndWordDescriptionAndSearchWord(getCardArgs()[0],getCardArgs()[1],mySearch));
}

public LiveData<List<Sentence>> getLiveCardList(){
    return cards;
}

}

ВЫЗОВ АДАПТЕРА В МОЕМ ФРАГМЕНТЕ

private void setUpCardViewModelObserver(String[] args) {


        cardViewModel.getLiveCardList().observe(getViewLifecycleOwner(), sentenceList -> {
            if (sentenceList != null) {
                ArrayList<Visitable> list = new ArrayList<>(sentenceList);
                cardAdapter.refreshDiffUtilsList(list);
                checkResults(list.size());
            }
        });


}

private void setUpGroupViewModelObserver() {
    groupViewModel.getGroups().observe(getViewLifecycleOwner(), groupsWithSentencesList -> {
        if (groupsWithSentencesList != null) {
            ArrayList<Visitable> list = new ArrayList<>(groupsWithSentencesList);
            cardAdapter.refreshDiffUtilsList(list);
            checkResults(groupsWithSentencesList.size());
        }
    });
}

Любая помощь приветствуется, большое спасибо.

1 Ответ

0 голосов
/ 05 ноября 2019

Таким образом, ответом было использование данных Mediator Live, я настраивал новые данные-посредники для реагирования на изменения в существующих объектах данных в реальном времени, а затем опосредовал эти изменения, чтобы у меня теперь был только один поток данных, поэтому модель представления моей карты теперьвыглядит так

public CardViewModel(@NonNull Application application , int clicks, String[] cardArgs){
    sentenceRepository = new SentenceRepository(application);
    search = new MutableLiveData<>();
    cards = Transformations.switchMap(search, mySearch -> sentenceRepository.searchLiveCardListByWordTypeAndWordDescriptionAndSearchWord(cardArgs[0],cardArgs[1],mySearch));
    groupRepository = new GroupRepository(application);
    groups = groupRepository.getGroupsByWordDescriptionAndWordType(cardArgs[0],cardArgs[1]);
    sentencesAndGroups = new MediatorLiveData<>();

    sentencesAndGroups.addSource(cards, sentences -> {
        sentencesAndGroups.setValue(combineLatest(sentences, groups.getValue()));
    });

    sentencesAndGroups.addSource(groups, groupsWithSentences -> {
        sentencesAndGroups.setValue(combineLatest(cards.getValue(), groupsWithSentences));
    });

}

, а мой новый комбайн последний метод выглядит так

private List<Visitable> combineLatest(List<Sentence> sentenceList, List<GroupsWithSentences> groupsWithSentences) {
    List<Visitable> visitableList = new ArrayList<>();
    if (sentenceList != null){
        visitableList.addAll(sentenceList);
    }
    if (groupsWithSentences != null){
        visitableList.addAll(groupsWithSentences);
    }
    return visitableList;
}
...