0

我有一个启动三个片段的活动。第一个是加载启动画面,我只想在其中显示应用程序的名称几秒钟。第二个,在我目前的情况下,是一个收集用户名和语言的屏幕。第三个片段将收集他们想学习的语言。我试图在我的 ViewModel 中使用 Observable 来保存我的数据,但是在第一个片段中输入的信息在切换到第二个片段时会丢失。

我想我同时遇到了两个(或更多)问题:

  1. 我认为我没有跨片段正确共享我的 runOnceViewModel
  2. 我不认为我使用 Observables 很正确。

从初始屏幕检查权限后,我触发一个函数(launchProfile),它加载下一个片段,如下所示:

public void launchProfile(){

        if(model.getLearnerPK() > 0){
            learningScreenFragment fragment = new learningScreenFragment(model.getUser());
            getParentFragmentManager()
                    .beginTransaction()
                    .addToBackStack(null)
                    .replace(R.id.fragment_container, fragment, null)
                    .commit();
        } else {
            runOnceNameAndNativeLangFragment fragment = new runOnceNameAndNativeLangFragment();
            getParentFragmentManager()
                    .beginTransaction()
                    .addToBackStack(null)
                    .replace(R.id.fragment_container, fragment, null)
                    .commit();
        }
    }

由于这是一个新用户,主键将为 0,因此我加载了 runOnceNameAndNativeLangFragment:

 @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        Log.d(LOG_TAG, "RUNONCE: Gather Name and Native Language");

        mBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.runonce_name_native, container, false);

        TransitionInflater TI = TransitionInflater.from(requireContext());
        setEnterTransition(TI.inflateTransition(R.transition.slide_right));

        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState){
        runOnceViewModelFactory factory = new runOnceViewModelFactory(requireActivity().getApplication());
        model = new ViewModelProvider(this,factory).get(runOnceViewModel.class);
        //super.onViewCreated(view,savedInstanceState); //remains of a road I tried to go down, but perhaps should have gone farther...
        //model = new ViewModelProvider(requireActivity()).get(runOnceViewModel.class);

        ArrayList<language> spinnerListLangs = model.getLangList();

        nativeSLAdapter = new SpinLangAdapter(m_Context, android.R.layout.simple_spinner_dropdown_item, spinnerListLangs);
        mBinding.spCreateNativeLang.setAdapter(nativeSLAdapter);

        mBinding.spCreateNativeLang.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
                language lang = nativeSLAdapter.getItem(position);
                tmpNativeLangNo = lang.getLangNo();
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {}
        });

        mBinding.btnNext.setOnClickListener(this::onClick);
    }



    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.btnNext) {
            String tmpName = mBinding.etCreateProfileName.getText().toString();
            if(tmpNativeLangNo != null && !tmpName.equals("")){

                model.getNewUser().observeOn(Schedulers.io()) //I'm doing something dumb here
                        .map(user -> {
                            user.setName(tmpName);
                            user.setNativeLang(tmpNativeLangNo);
                            return user;
                        });

                runOnceSelectTargetLangsFragment fragment = new runOnceSelectTargetLangsFragment();
                getParentFragmentManager()
                        .beginTransaction()
                        .addToBackStack(null)
                        .replace(R.id.fragment_container, fragment, null)
                        .commit();
            } else {
                Toast.makeText(m_Context,"Name and Native Language required.",Toast.LENGTH_SHORT).show();
            }
        }
    }

如果我在“runOnceSelectTargetLangsFragment fragment = new runOnceSelectTargetLangsFragment();”上设置断点 然后我可以验证 model.getNewUser() 返回一个 Observable,其中包含我在 UI 上输入的任何内容的名称和母语。让我感到沮丧的是,一旦我加载下一个片段(runOnceSelectTargetLangsFragment),并尝试将目标语言保存在其点击处理程序中,名称和本地语言信息就会丢失。唉,我没有正确共享视图模型(或者,更糟糕的是,我在不应该使用的时候使用了 Observable——旁注:我选择使用 Observable 是因为它使处理线程的东西变得相当容易,而且我想随着应用程序变得越来越复杂,我会欣赏它的灵活性。至少,我是这么告诉自己的。)

选择目标片段

@Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        Log.d(LOG_TAG, "RUNONCE: Gather Target Languages");

        mBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.runonce_select_targets, container, false);

        TransitionInflater TI = TransitionInflater.from(requireContext());
        setEnterTransition(TI.inflateTransition(R.transition.slide_right));

        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState){
        //runOnceViewModelFactory factory = new runOnceViewModelFactory(requireActivity().getApplication());
        //model = new ViewModelProvider(this,factory).get(runOnceViewModel.class); //I think this was on the right track...maybe?
        //super.onViewCreated(view,savedInstanceState);
        model = new ViewModelProvider(requireActivity()).get(runOnceViewModel.class);

        mBinding.btnNext.setOnClickListener(this::onClick);
    }


    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.btnNext) {
            if(hasChecked()){

                model.getNewUser().observeOn(Schedulers.io())
                        .subscribe(user -> {
                            user.setTargetLangs(getTargetLangs());
                        });

               String restHereWearyTraveler = ""; //the inn :)
               //...do more stuff 
    
            } else {
                Toast.makeText(m_Context,"You must select at least one target language.",Toast.LENGTH_SHORT).show();
            }
        }
    }

在客栈,model.getNewUser() 返回一个 Observable,目标语言都设置好了,但是名字和母语信息都没有了。

查看模型

public class runOnceViewModel extends AndroidViewModel {

    private final profileRepository m_Repository;
    private profileService PCS;
    private ArrayList<language> m_Langs;
    private Observable<User> newUser;

    public runOnceViewModel(Application application, profileRepository newProfileRepo) {
        super(application);
        m_Repository = newProfileRepo;
        m_Langs = m_Repository.getLanguages();
        PCS = profileService.getInstance(m_Repository);
    }

    public Observable<User> getNewUser(){
        if(newUser == null){
            User tmpUser = new User();
            newUser = Observable.just(tmpUser);
        }
        return newUser;
    }
}
4

0 回答 0