繁体   English   中英

如何根据微调器选择MVVM + LiveData更新recyclerview

[英]How to update recyclerview based on spinner selection MVVM + LiveData

我有一个 Android 应用程序(Java),它使用 MVVM + LiveData 按季节显示节目列表。 当用户第一次登陆片段时,我希望第 1 季的标题显示在 RecyclerView 中。 然后我希望用户能够 select 另一个赛季然后显示这些标题。 我可以将所选季节发送到我的 ViewModel,但我不知道如何使用所选季节的标题更新我的 RecyclerView。 任何帮助是极大的赞赏!

这是我的片段:

    public class ShowFragment extends Fragment {
        private ShowTitlesAdapter showTitlesAdapter;
        private ArrayList<Titles> titlesList;
    
        private FragmentShowBinding binding;
        private TitlesViewModel titlesViewModel;
        private String ShowTag, ShowTitle, ShowImgUrl;
        private RecyclerView rvTitles;
        private Spinner popupSpinner;
    
        public ShowFragment() {
            // Required empty public constructor
        }
    
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            binding = FragmentShowBinding.inflate(inflater, container, false);
            View view = binding.getRoot();
            return view;
        }
    
        @Override
        public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
    
            titlesList = new ArrayList<>();
    
            titlesViewModel = new ViewModelProvider(this).get(TitlesViewModel.class);
            initAdapter();
            init();
    
            ShowFragmentArgs args = ShowFragmentArgs.fromBundle(getArguments());
            ShowTag = args.getFranchiseTag();
            titlesViewModel.getAllTitles(ShowTag);
    
            ShowImgUrl = args.getShowImg();
            ShowTitle = args.getShowTitle();
    
            titlesViewModel.getAllTitles(ShowTitle);
            binding.showTitle.setText(ShowTitle);
            Drawable placeHolder = getResources().getDrawable(R.drawable.placeholder_1080x1080);
    
            Glide.with(getContext())
                    .load(ShowImgUrl) //image url
                    .placeholder(placeHolder)
                    .into(binding.showImage);
        }
    
        private void initAdapter() {
            binding.rvTitles.setLayoutManager(new LinearLayoutManager(getContext()));
            showTitlesAdapter = new ShowTitlesAdapter(getContext(), titlesList);
            binding.rvTitles.setAdapter(showTitlesAdapter);
        }
    
    
        private void init() {
            titlesList.clear();
    
            titlesViewModel.sortedSeasonListOne.observe(getViewLifecycleOwner(), new Observer<List<Titles>>() {
                @Override
                public void onChanged(List<Titles> titles) {
                    titlesList.addAll(titles);
                    showTitlesAdapter.setShowTitlesList(titlesList);
                }
            });
            titlesViewModel.getAllTitles(ShowTag);
    
            createDropDownList(titlesList);
        }
    
    
        public void createDropDownList(ArrayList<Titles> titles) {
            List<String> seasonListStr = new ArrayList<>();
    
            titlesViewModel.seasonsStrList.observe(getViewLifecycleOwner(), new Observer<List<String>>() {
                @Override
                public void onChanged(List<String> seasons) {
                    seasonListStr.addAll(seasons);
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        seasonListStr.replaceAll(s -> "Season " + s);
                    }
                    ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1, seasonListStr);
                    adapter.setDropDownViewResource(android.R.layout.simple_list_item_1);
                    binding.popupSpinner.setAdapter(adapter);
                    binding.popupSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    
                        @Override
                        public void onItemSelected(AdapterView<?> parent, View view, int position, long l) {
                            titlesViewModel.populateTitlesInSeason(parent.getItemAtPosition(position).toString());
//                        showTitlesAdapter.setShowTitlesList(titlesList); --> I don't know how to update this list with another season of titles!
                        }
    
                        @Override
                        public void onNothingSelected(AdapterView<?> adapterView) {
                        }
                    });
                    binding.popupSpinner.setAdapter(adapter);
                }
            });
        }
    

        @Override
        public void onDestroyView() {
            super.onDestroyView();
            binding = null;
        }
    }

视图模型:

public class TitlesViewModel extends ViewModel {
    Repository repository;
    private final io.reactivex.rxjava3.disposables.CompositeDisposable disposables = new CompositeDisposable();

    public MutableLiveData<ArrayList<Titles>> titlesListLiveData;
    public List<String> seasonsList;
    public LiveData<List<Titles>> sortedList;
    public LiveData<List<Titles>> sortedSeasonListOne;
    public LiveData<List<Titles>> sortedSeasonListSeason;
    public LiveData<List<Integer>> seasons;
    public LiveData<List<String>> seasonsStrList;


    @Inject
    public TitlesViewModel(Repository repository) {
        this.repository = repository;
        titlesListLiveData = repository.getTitlesLiveData();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            sortedList = Transformations.map(titlesListLiveData, titlesList -> titlesList.stream().sorted(Comparator.comparing(Titles::getSeasonNumber).thenComparing(Titles::getEpisodeNumber)).collect(Collectors.toList()));
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            seasons = Transformations.map(sortedList, list -> list.stream().map(Titles::getSeasonNumber).distinct().collect(Collectors.toList()));
            seasonsStrList = Transformations.map(seasons, strList -> strList.stream().map(Object::toString).collect(Collectors.toList()));
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            sortedSeasonListOne = Transformations.map(titlesListLiveData, srtList -> srtList.stream().sorted(Comparator.comparing(Titles::getSeasonNumber).thenComparing(Titles::getEpisodeNumber)).filter(list ->1 == list.getSeasonNumber()).collect(Collectors.toList()));
        }

    }

    public void populateTitlesInSeason(String season) {
        String seasonNo = season.substring(7);
        int seasonNum = 1;
        try{
            seasonNum = Integer.parseInt(seasonNo);

        }catch(NumberFormatException ex){

        }


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            int finalSeasonNum = seasonNum;
            sortedSeasonListSeason = Transformations.map(titlesListLiveData, seasonList -> seasonList.stream().sorted(Comparator.comparing(Titles::getSeasonNumber).thenComparing(Titles::getEpisodeNumber)).filter(list -> finalSeasonNum == list.getSeasonNumber()).collect(Collectors.toList()));
        }
    }

    /////////Titles
    public void getAllTitles(String tag) {
        repository.getAllTitles(tag);
    }


    @RequiresApi(api = Build.VERSION_CODES.N)
    public MutableLiveData<ArrayList<Titles>> getTitlesListLiveData() {
        return repository.getTitlesLiveData();
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        disposables.clear();
    }
}

存储库:

public class Repository {

    final ApiService apiService;

    private final MutableLiveData<ArrayList<Titles>> titlesList = new MutableLiveData<>();

    @Inject
    public Repository(ApiService service){this.apiService = service;}

    public void getAllTitles(String tag){
        apiService.getTitles(tag).enqueue(new Callback<ArrayList<Titles>>() {

            @Override
            public void onResponse(Call<ArrayList<Titles>> call, Response<ArrayList<Titles>> response) {
                if (response.body() != null) {
                    titlesList.postValue(response.body());
                }
            }

            @Override
            public void onFailure(Call<ArrayList<Titles>> call, Throwable t) {
                Log.d("Titles","onFailure"+Thread.currentThread().getName());
            }
        });
    }

    public MutableLiveData<ArrayList<Titles>> getTitlesLiveData(){
        return titlesList;
    }

}

RecyclerView 适配器:

public class ShowTitlesAdapter extends RecyclerView.Adapter<ShowTitlesAdapter.ShowTitlesViewHolder> {
    private ItemShowTitleBinding binding;
    private ArrayList<Titles> showTitles;

    private Context context;
    int pos;

    public ShowTitlesAdapter(Context context, ArrayList<Titles> showTitles){
        this.context = context;
        this.showTitles = showTitles;
    }

    @NonNull
    @Override
    public ShowTitlesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(context);
        binding = ItemShowTitleBinding.inflate(inflater, parent, false);
        return new ShowTitlesViewHolder(binding);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onBindViewHolder(@NonNull ShowTitlesViewHolder holder, int position) {
        holder.binding.showTitleLayout.setClipToOutline(true);
        holder.binding.episodeNo.setText(Integer.toString(showTitles.get(position).getEpisodeNumber()));
        holder.binding.episodeTitle.setText(showTitles.get(position).getTitle());
        pos = position;
        holder.binding.showTitleLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ShowFragmentDirections.ActionShowFragmentToMovieShowDetailFragment action =
                        ShowFragmentDirections.actionShowFragmentToMovieShowDetailFragment(showTitles.get(position).getId(), showTitles.get(position).getFranchiseTag());
                Navigation.findNavController(v).navigate((NavDirections) action);
            }
        });
    }

    @Override
    public int getItemCount() {
        if(showTitles != null){
            return showTitles.size();
        }
        return 0;
    }

    public class ShowTitlesViewHolder extends RecyclerView.ViewHolder {

        private ItemShowTitleBinding binding;

        public ShowTitlesViewHolder(ItemShowTitleBinding binding) {
            super(binding.getRoot());
            this.binding = binding;

        }
    }

    public void setShowTitlesList(ArrayList<Titles> showTitles){
        this.showTitles = showTitles;
        notifyDataSetChanged();
    }

}

简而言之:

  1. ShowFragment中,您需要观察sortedSeasonListSeasonTitlesViewModel
  2. 当您收到具体季节时,您应该将其传递给populateTitlesInSeason (您已经这样做了)
  3. populateTitlesInSeason方法中,您应该通过MutableLiveDatasortedSeasonListSeason列表传回ShowFragment
  4. 所以你需要在TitlesViewModel中为sortedSeasonListSeason列表创建MutableLiveData以传递选定的数据,例如sortedSeasonListSeasonLiveData
  5. 所以你只需要sortedSeasonListSeasonLiveData.postValue(sortedSeasonListSeason)
  6. 现在回到ShowFragment并从我的指令的第 1 阶段处理观察者中收到的具体标题列表

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM