如何从2个视图模型更新1个回收站视图适配器?

时间:2019-11-05 17:17:44

标签: android android-recyclerview recycler-adapter android-livedata android-viewmodel

我有2个视图模型,它们观察房间中的2个表,每个表都发出实时数据,当值更改时,它们应该更新我的回收者视图。我的适配器可以处理多个模型和视图支架,但是我不确定如何用新数据更新回收者视图适配器,而又不会覆盖当前数据或复制任何想法的数据吗?

因此我的适配器采用了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();
}

}

我的2个视图模型位于一个片段中,它们观察我的Room数据库中的一些数据,并在发生更改时进行更新,但这意味着我将永远只能使用其中一个视图模型中的数据,我想我想要一种方法为了合并这些视图模型(也许使用某种中介者实时数据),这是我的2个视图模型(为简便起见,我删除了一些东西,它们都是使用工厂启动的)

组视图模型

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 :(得分:0)

所以答案是使用Mediator Live数据,我设置了新的Mediator Live数据以响应对我现有的live data对象的更改,然后调解这些更改,因此我现在只有一个数据流,所以现在我的名片视图模型看起来像这样

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;
}