android - MVVM 设置 Recyclerview 适配器,其中包含 fragment 中的项目

标签 android android-fragments mvvm android-recyclerview

我第一次使用 MVVM 模式与改造和回收 View 。我已经在我的 viewmodel 类中进行了网络调用,但不知道如何在 recyclerview 中显示数据。

这是我的 View 模型代码:

public class HomeSessionsViewModel extends ViewModel {

private static final String TAG = HomeSessionsViewModel.class.getSimpleName();

private Context context;

public String sessionImg;
public String title, programName, batchName, batchPlayersCount;

public HomeSessionsViewModel(Context context) {
    this.context = context;
}

public void fetchSessions(String coachId){
    Log.d(TAG, "Call made");
    Call<SessionDetails> call = RestClient.getRestInstance()
            .getSessionsService()
            .fetchSessions(coachId);

    call.enqueue(new Callback<SessionDetails>() {
        @Override
        public void onResponse(Call<SessionDetails> call, Response<SessionDetails> response) {
            if (response.isSuccessful()){
                SessionDetails details = response.body();
                List<Sessions> sessions = details.getSessions();
                for (int i = 0; i < sessions.size(); i++){
                    Log.d(TAG, "Session Name:\t" + sessions.get(i).session_name);
                    sessionImg = sessions.get(i).sessionImage;
                    title = sessions.get(i).session_name;
                    programName = sessions.get(i).program_name;
                    batchName = sessions.get(i).batch_name;
                    batchPlayersCount = sessions.get(i).participants_count;
        //          addData(sessions);
                }
            }
        }

        @Override
        public void onFailure(Call<SessionDetails> call, Throwable t) {
            Log.d(TAG, "Can't Get Sessions:\n");
            Log.d(TAG, t.getMessage());
        }
    });

}

}

和适配器代码:

public class SessionsAdapter extends RecyclerView.Adapter<SessionsViewHolder> {

private final Context context;
private List<HomeSessionsViewModel> itemsList;

public SessionsAdapter(Context context, List<HomeSessionsViewModel> itemsList) {
    this.context = context;
    this.itemsList = itemsList;
}

@Override
public SessionsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    HomeSessionsBinding sessionsBinding = HomeSessionsBinding.inflate(inflater, parent, false);
    return new SessionsViewHolder(sessionsBinding);
}

@Override
public void onBindViewHolder(SessionsViewHolder viewholder, int position) {
    HomeSessionsViewModel viewModel = itemsList.get(position);
    viewholder.bindSessions(viewModel);
}

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

}

在我的 fragment 中我有这个:

public class HomeFragment extends Fragment implements OnItemClickedListener, DatePickerListener {

private RecyclerView actionsRV, sessionsRV;
private List<ActionsViewModel> actionsList = new ArrayList<>();
private ActionsAdapter actionsAdapter;

private HomeFragmentBinding fragmentBinding;
private HomeFragmentViewModel homeViewModel;
private HomeSessionsViewModel sessionsViewModel;

private List<HomeSessionsViewModel> sessionsViewModelList = new ArrayList<>();
private SessionsAdapter sessionsAdapter;

@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                         @Nullable Bundle savedInstanceState) {
    fragmentBinding = DataBindingUtil.inflate(inflater, R.layout.home_fragment, container, false);
    homeViewModel = new HomeFragmentViewModel(getActivity());
    fragmentBinding.setHomeViewModel(homeViewModel);
    init();
    return fragmentBinding.getRoot();
}

private void init() {
    addActions();
    initPicker();
    populateSessions();
}

private void initPicker() {
    fragmentBinding.datePicker.setListener(this)
            .setMonthAndYearTextColor(getActivity().getResources().getColor(R.color.white))
            .setDateSelectedColor(getActivity().getResources().getColor(R.color.white))
            .setDateSelectedTextColor(getActivity().getResources().getColor(R.color.event_color_03))
            .setTodayButtonTextColor(getActivity().getResources().getColor(R.color.white))
            .setTodayDateTextColor(getActivity().getResources().getColor(R.color.accent))
            .setUnselectedDayTextColor(getActivity().getResources().getColor(R.color.white))
            .init();
}

private void populateSessions() {
    sessionsViewModel = ViewModelProviders.of(this).get(HomeSessionsViewModel.class);
    sessionsViewModel.fetchSessions("4086");
  //sessionsViewModel.fetchSessions();
  //sessionsViewModel.fetchSessions(""); // TODO: 3/16/2019 Use coach id from db

    sessionsRV = fragmentBinding.sessionsRV;
  //sessionsViewModelList = sessionsViewModel.items();
    sessionsAdapter = new SessionsAdapter(getActivity(), sessionsViewModelList);


}

private void addActions() {
    actionsRV = fragmentBinding.actionsRV;
    actionsRV.setHasFixedSize(true);
    LinearLayoutManager hlm = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
    fragmentBinding.actionsRV.setLayoutManager(hlm);

    ActionsViewModel action1 = new ActionsViewModel();
    action1.name = "Attendance";
    action1.img = getResources().getDrawable(R.drawable.ic_attendance);
    actionsList.add(action1);

    ActionsViewModel action2 = new ActionsViewModel();
    action2.name = "Evaluate";
    action2.img = getResources().getDrawable(R.drawable.ic_evaluate);
    actionsList.add(action2);

    ActionsViewModel action3 = new ActionsViewModel();
    action3.name = "Players";
    action3.img = getResources().getDrawable(R.drawable.ic_players);
    actionsList.add(action3);

    ActionsViewModel action4 = new ActionsViewModel();
    action4.name = "Programs";
    action4.img = getResources().getDrawable(R.drawable.ic_programs);
    actionsList.add(action4);

    ActionsViewModel action5 = new ActionsViewModel();
    action5.name = "Tips/VOD";
    action5.img = getResources().getDrawable(R.drawable.ic_tips_vod);
    actionsList.add(action5);

    actionsAdapter = new ActionsAdapter(getActivity(), actionsList);
    actionsAdapter.setItemClickedListener(this);
    actionsRV.setAdapter(actionsAdapter);

}

@Override
public void itemClicked(int position) {
    switch (position){
        case 0:
            Toast.makeText(getActivity(), "Attendance Clicked", Toast.LENGTH_SHORT).show();
            break;
        case 1:
            Toast.makeText(getActivity(), "Evaluate Clicked", Toast.LENGTH_SHORT).show();
            break;
        case 2:
            Toast.makeText(getActivity(), "Players Clicked", Toast.LENGTH_SHORT).show();
            break;
        case 3:
            Toast.makeText(getActivity(), "Programs Clicked", Toast.LENGTH_SHORT).show();
            break;
        case 4:
            Snackbar.make(getActivity().findViewById(android.R.id.content), "Tips Coming Soon", Snackbar.LENGTH_SHORT).show();
            break;
    }
}

@Override
public void onDateSelected(DateTime dateSelected) {

}
}

显示 recyclerview 操作很简单,但我不确定如何进行 session 。我已关注this tutorial series但我不知道如何将数据从 View 模型获取到 fragment 回收器 View 中。我读过,将 View 小部件添加到 View 模型中可能会导致内存泄漏。有什么办法可以做到这一点吗?谢谢。

最佳答案

您可以将 LiveData 用于此类目的。 LiveData 具有生命周期感知能力,可以在 ViewModel 中使用。

在您的 ViewModel 中,添加 MutableLiveData 类型的属性。

private MutableLiveData<List<Session>> sessionsLiveData = new MutableLiveData<List<Session>>();

public LiveData<List<Session>> getSessionLiveData(){
    return sessionsLiveData;
}

当进行网络调用并且您拥有适配器所需的数据时,请为此 LiveData 设置值。

call.enqueue(new Callback<SessionDetails>() {
        @Override
        public void onResponse(Call<SessionDetails> call, Response<SessionDetails> response) {
            if (response.isSuccessful()){
                SessionDetails details = response.body();
                List<Session> sessions = details.getSessions();
                sessionsLiveData.postValue(sessions);
            }
        }

        @Override
        public void onFailure(Call<SessionDetails> call, Throwable t) {
            Log.d(TAG, "Can't Get Sessions:\n");
            Log.d(TAG, t.getMessage());
        }
    });

在您的 fragment 中,观察此LiveData

viewModel.getSessionLiveData().observe(this, new Observer<List<Session>>() {
            @Override
            public void onChanged(@Nullable final List<Session> sessions) {
                // set Data to adapter here.
                adapter.setData(sessions);
            }
        });

关于android - MVVM 设置 Recyclerview 适配器,其中包含 fragment 中的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55204497/

相关文章:

WPF 用户控件 : Have a Command that is only available internally in the UserControl

android - 使用 Jitsi Sdk 和 Quickblox-android-sdk 时重复类 org.webrtc.AndroidVideoDecoder

java - Android中Activity创建后如何执行代码?

java.lang.IllegalStateException : GoogleApiClient is not connected yet 错误

android - Firefox for Android (v18) CSS 重置?

xml - 将片段中的布局项目约束到主事件底部栏导航的顶部?

android - 如何为 viewpager fragment 设置标签?

java - InflateException 二进制 XML 文件,第 7 行 : Error inflating class fragment

Swift 覆盖泛型 swift

c# - 从文本框更改为组合框