微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 RxJava3

如何解决使用 RxJava3

概述 我正在尽力遵循 MVVM 模式。在我的数据模型中,我有一个实体“语言”及其通过存储库访问的相应 DAO。反过来,这个存储库提供我的视图模型,并通过我的片段中的工厂进行实例化。或者,从另一个方面来说,我的片段 -> viewmodelFactory -> viewmodel -> Repository -> DAO -> Entity

我对 ArrayAdapter 在何处“适合”MVVM 模式感到有些困惑。该特定片段旨在显示一系列字段(姓名、语言等),用作应用内的“个人资料”创建页面

问题: 我试图用语言列表填充微调器,这样当微调器中的一种语言被选择时,相应的值实际上会在软件中使用(想想:文本值对)。我真的不知道我在做什么,但我正在尽可能快地失败。目前,我在片段 onViewCreated 方法中遇到以下错误

Android Studio 错误:“无法解析‘Observable’中的‘observe’方法

代码

语言实体

@Entity
public class languages {
    @PrimaryKey(autoGenerate = true)
    @NonNull
    public Long langNo;
    public String langDesc;
    @ColumnInfo(defaultValue = "CURRENT_TIMESTAMP")
    public Long langUpdatedDate;
    @ColumnInfo(defaultValue = "CURRENT_TIMESTAMP")
    public Long langCreatedDate;
}

DAO

@Dao
public interface languagesDAO {
    @Update
    Completable update(languages language);

    @Insert
    Completable insert(languages language);

    @Delete
    Completable delete(languages language);

    //for array deletion
    @Delete
    Completable delete(languages... language);

    //Queries
    @Query("SELECT * FROM languages;")
    Single<List<languages>> getLanguages();
}

存储库

public class newProfileRepository {
    private final syllableDB m_db;
    private static newProfileRepository s_Instance;
    private usersDAO u_dao;
    private languagesDAO l_dao;
    private usersXlanguagesDAO uxl_dao;
    

    public newProfileRepository(final syllableDB db){
        m_db  = db;
        u_dao = m_db.usersDao();
        l_dao = m_db.languagesDAO();
        uxl_dao = m_db.usersXlanguagesDAO();
    }

    public static newProfileRepository getInstance(final syllableDB db) {
        if (s_Instance == null) {
            synchronized (newProfileRepository.class) {
                if (s_Instance == null) {
                    s_Instance = new newProfileRepository(db);
                }
            }
        }
        return s_Instance;
    }

    public Single<List<languages>> getLanguages(){
        return l_dao.getLanguages();
    }
    //...
}

SpinLangAdapter

public class SpinLangAdapter extends ArrayAdapter<language> {

    private Context context;
    private ArrayList<language> tvPairs = new ArrayList<>();
    private List<languages> langs;
    private newProfileRepository newP_repo;
    private syllableDB db;

    public SpinLangAdapter(Context context,int textViewResourceId,List<language> list){
        super(context,textViewResourceId);
        this.context = context;
        this.tvPairs = new ArrayList<language>(list);
    }


    //This isn't used as I'm not even getting this far...
    public void setLangs(List<languages> newLangs){
        langs = newLangs;
        notifyDataSetChanged();
    }

   /* @Override
    public int getCount(){
        return tvPairs.size();
    }

    @Override
    public language getItem(int position){
        return tvPairs.get(position);
    }*/

    @Override
    public long getItemId(int position){
       return position;
    }

    //SO Link: https://stackoverflow.com/questions/1625249/android-how-to-bind-spinner-to-custom-object-list   
    //again,not used (yet)
    /*@Override
    public View getView(int position,View convertView,ViewGroup parent) {        
        TextView label = (TextView) super.getView(position,convertView,parent);
        label.setTextColor(Color.BLACK);        
        label.setText(tvPairs.get(position).getLangDesc());
        return label;
    }*/
}

视图模型

public class createNewProfileviewmodel extends Androidviewmodel {
    private static final String QUERY_KEY = "QUERY";

    private final newProfileRepository m_Repository;
    private Single<List<languages>> m_Langs;   

    public createNewProfileviewmodel(Application application,newProfileRepository newProfileRepo) {
        super(application);
        m_Repository = newProfileRepo;
        m_Langs = m_Repository.getLanguages();
       
    }
   
    public Observable<List<languages>> getLangListObservable(){
        Single<List<languages>> items = m_Repository.getLanguages();
        items.flattenAsObservable(new Function<List<languages>,Iterable<?>>() {
            @Override
            public Iterable<?> apply(List<languages> languages) throws Throwable {
                return languages;
            }
        })
        .toList();
        return null;
    }
}

片段

public class createNewProfileFragment extends Fragment implements View.OnTouchListener,View.OnClickListener {
    private static final String LOG_TAG = com.electricbamboo.syllable.ui.createNewProfileFragment.class.getSimpleName();
    private CreateNewProfileBinding mBinding;
    private Context m_Context;

    private profileService PCS;

    private SpinLangAdapter nativeSLAdapter;
    private SpinLangAdapter targetSLAdapter;
    private List<language> spinnerListLangs;

    private Float tmpFZero=null;
    private Long tmpNativeLangNo = 0L;
    private ArrayList<Long> tmpTargetLangNos = new ArrayList<>();

    public createNewProfileFragment(){}

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        m_Context = context;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,@Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {
        Log.d(LOG_TAG,"Starting New Profile Creation");

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

        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view,@Nullable Bundle savedInstanceState){
        newProfileviewmodelFactory factory = new newProfileviewmodelFactory(requireActivity().getApplication());

        final createNewProfileviewmodel model = new viewmodelProvider(this,factory).get(createNewProfileviewmodel.class);
        mBinding.setLifecycleOwner(getViewLifecycleOwner());

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

        targetSLAdapter = new SpinLangAdapter(m_Context,spinnerListLangs);
        mBinding.spCreateTargetLang.setAdapter(targetSLAdapter);

        // Doesn't compile,error thrown here ("Cannot resolve method 'observe' in 'Observable'")
        model.getLangListObservable().observe(this,new Observer<List<languages>>(){
            @Override
            public void onChanged(@Nullable final List<languages> langs){
                for(languages l : langs){
                    language tmpLang = null;
                    tmpLang.setLangNo(l.langNo);
                    tmpLang.setLangDesc(l.langDesc);
                    spinnerListLangs.add(tmpLang);
                }
                targetSLAdapter.notifyDataSetChanged();
                nativeSLAdapter.notifyDataSetChanged();
            }
        });

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

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

        mBinding.spCreateTargetLang.setonItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView,long l) {
                language language = targetSLAdapter.getItem(position);
                tmpTargetLangNos.add(language.getLangNo());
            }

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

        subscribetoModel(model);
    }

    private void subscribetoModel(final createNewProfileviewmodel model){
          //Fairly certain SOMETHING is supposed to go here,just unsure as to what
    }

  //...omitting onClick,onTouch,onStart,onPause,onResume,etc.

语言课 不要与语言混淆!

之所以存在,是因为我认为使用扩展 LiveData 而不是扩展的东西可能更容易 一个 RxJava Single。基于此处提供的答案:When to use RxJava in Android and when to use LiveData from Android Architectural Components? (看看 kzotin 的回应)。这是我的尝试。

public class language extends LiveData {
    private Long langNo;
    private String langDesc;

    //Getters
    public Long getLangNo(){
        return langNo;
    }

    public String getLangDesc(){
        return langDesc;
    }

    //Setters
    public void setLangNo(Long langNo){
        this.langNo = langNo;
    }

    public void setLangDesc(String langDesc){
        this.langDesc = langDesc;
    }

}

我的尝试

我真的尝试引入这里介绍的文本值对功能Populate Spinner from LiveData (Room Database) (这让我摸不着头脑,为什么“观察”会导致问题)。

使用此处介绍的 Observable 机制: Transform a Single<List<Item>> to an Observable<Item>?

...以及这里的 ID 内容(我已经评论了很多来自接下来两个链接代码,因为我什至没有走那么远): Android: How to bind spinner to custom object list?Android - configure Spinner to use array

通常困扰我的问题是我无法遍历带有 for-each 循环的 Single 对象,因为“foreach 未为 RxJava...Single 定义”(或类似的东西)当我将“语言”对象列表转换为“语言”对象列表。

我以为我可以将语言对象作为 Singles 检索,然后在 .map 或 .flatMap 函数中将它们添加到我的 onObservable 列表中,但这让我来到这里。

问题

  1. 对于 MVVM 模式,我选择在哪里访问我的存储库和处理 Spinner 的初始化是否合理?我想确保我正在使用该框架,而不是反对它,但我不知道我在做什么,并且使用 RxJava,感觉很好。我在想,如果我对如何更好地组织代码有一些指导,那么也许它可以阻止我尝试做一些愚蠢的事情。

  2. 我应该尝试让“中级”“language.java”类工作,还是完全放弃它?换句话说,我是否应该不担心将 RxJava 转换为 LiveData 可能有什么优势(或者我认为我理解的是什么)?好像我误解了一些东西,它混淆了我的代码,让我的生活变得更加艰难。

  3. 我应该怎样这样做?

  4. 我应该在我的 subscribetoModel 中做什么?我读过应该为服务保留业务逻辑。因此,到目前为止,在我看来,存储库应该负责传递计算内容,但我对如何对“填充”逻辑进行分类有点模糊,因此犹豫是否对片段进行任何类型的操作等级。然而,这让我想知道“好吧,那应该去那里做什么??”

非常感谢您提供的任何线索。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。