ViewModel模式-片段UI仅在屏幕旋转后更新

时间:2019-10-12 23:22:03

标签: java android android-fragments mvvm rotation

应用程序将片段与“视图模型”模式结合使用。在该片段中,将显示两个Spinners和RecylclerView。其中一个Spinner包含一个工作日,其中包含相应的练习,当更改Spinner的工作日选择时应更新这些练习。因此,我使用Livedata.observe()方法。在应用程序开始时,将加载当天的所有练习。此外,还将在练习中添加此列表的另一个元素以创建新的练习(我现在将该元素称为“添加练习”)。

当我现在将工作日更改为其他日期时,仅在旋转屏幕后才会更新列表。此外,每次旋转屏幕时,都会添加一个附加的“添加锻炼”项目。基于这种行为,我意识到即使屏幕与Spinner元素没有任何交互,每次旋转屏幕时,Spinner Listener的onItemSelected()方法也会被激活。

此外,如果更改为另一个片段,所有加载的数据和Spinner元素的选择都将丢失(据我了解,ViewModel,这正是应该借助ViewModel类来防止的)。

最后,这是我的问题:

  1. 为什么只在旋转屏幕后才更新屏幕?
  2. 为什么在之后Spinner元素的onItemSelected()调用 即使没有任何互动,我也会旋转屏幕 微调元素?
  3. 为什么切换后丢失片段或ViewModel数据 到另一个片段?

从HomeViewModel中提取:

public class HomeViewModel extends ViewModel {

    private static final String TAG = "HomeViewModel";

    private MutableLiveData<List<Exercise>> mExercises;
    private MutableLiveData<List<TrainingPlan>> mTrainingPlans;
    private MutableLiveData<Integer> calendarDay;
    private TrainingPlan selectedTrainingPlan;

    final Exercise addExercise = Exercise.builder().name("ADD EXERCISE").sets(null).build();

    private List<TrainingPlan> trainingPlans;
    private List<Exercise> currentExercises;

    public HomeViewModel() {
        mTrainingPlans = new MutableLiveData<>();
        mExercises = new MutableLiveData<>();

        TrainingsPlanDAO trainingsPlanDAO = new DummyTrainingsPlanDAO();
        trainingPlans = trainingsPlanDAO.searchAll();



        setSelectedTrainingPlanToDefaultTrainingPlan(trainingPlans);

        currentExercises = getExercisesOfTheCurrentDay();

        if(currentExercises.isEmpty()){
            Log.i(TAG, "No Exercises for the current day!");
        }

        mTrainingPlans.setValue(trainingPlans);
        mExercises.setValue(currentExercises);


        //additional Exercise in the list for Add function of new Exercise
        currentExercises.add(addExercise);
    }

    public LiveData<List<Exercise>> getExercises() {
        return mExercises;
    }

    public Integer getCurrentDay(){ return getCalendarDay(); }

    public LiveData<List<TrainingPlan>> getTrainingPlans(){ return mTrainingPlans; }


    public void setmExercisesToDay(int day){
        List<Exercise> exercises = getExercisesOfDay(day);
        exercises.add(addExercise);
        mExercises.setValue(exercises);
    }


    private void setSelectedTrainingPlan(TrainingPlan selectedTrainingPlan){
        this.selectedTrainingPlan = selectedTrainingPlan;
    }...

HomeFragment:

public class HomeFragment extends Fragment {

    private HomeViewModel homeViewModel;

    private ExerciseRecyclerViewAdapter exerciseAdapter;
    private ArrayAdapter<CharSequence> weekdayAdapter;
    private ArrayAdapter<TrainingPlan> trainingPlanAdapter;

    View root;


    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        homeViewModel =
                ViewModelProviders.of(this).get(HomeViewModel.class);
        root = inflater.inflate(R.layout.fragment_home, container, false);

        initElements();

        return root;
    }


    private void initElements(){
        initWeekdaySpinner();
        initTrainingPlanSpinner();
        initRecylerView();
    }


    private void initWeekdaySpinner(){
        final Spinner currentDaySpinner = root.findViewById(R.id.currentDay_spinner);

        currentDaySpinner.setOnItemSelectedListener(countrySelected);

        weekdayAdapter = ArrayAdapter.createFromResource(getActivity(), R.array.weekdays, android.R.layout.simple_spinner_item);
        weekdayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        currentDaySpinner.setAdapter(weekdayAdapter);

        currentDaySpinner.setSelection(mapWeekdayFromCalenderDayToSpinnerPosition(homeViewModel.getCurrentDay()));
    }


    private void initTrainingPlanSpinner(){
        final Spinner trainingPlanSpinner = root.findViewById(R.id.currentPlan_spinner);

        trainingPlanAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item, homeViewModel.getTrainingPlans().getValue());
        trainingPlanAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        trainingPlanSpinner.setAdapter(trainingPlanAdapter);
    }


    private void initRecylerView(){
        final RecyclerView recyclerView = root.findViewById(R.id.exercise_recyclerView);

        homeViewModel.getExercises().observe(this, new Observer<List<Exercise>>() {
            @Override
            public void onChanged(@Nullable List<Exercise> mExercises) {
                exerciseAdapter.notifyDataSetChanged();
            }
        });

        exerciseAdapter = new ExerciseRecyclerViewAdapter(getActivity(), homeViewModel.getExercises().getValue());
        RecyclerView.LayoutManager linearLayoutManager = new LinearLayoutManager(this.getContext());
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.setAdapter(exerciseAdapter);
    }


    AdapterView.OnItemSelectedListener countrySelected = new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            homeViewModel.setmExercisesToDay(mapWeekdayFromSpinnerPositionToCalenderDay(position));
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    };


    private int mapWeekdayFromCalenderDayToSpinnerPosition(int integer){
        return (integer + 5) % 7;
    }


    private int mapWeekdayFromSpinnerPositionToCalenderDay(int integer){
        return (integer + 2) % 7;
    }
}

0 个答案:

没有答案