使用RxJava3在房间数据库的片段中填充微调器的问题
概述 我正在尽力遵循MVVM模式。在我的数据模型中,我有一个实体“languages”及其通过存储库访问的对应DAO。这个存储库反过来为我的viewmodel提供信息,并通过片段中的工厂进行实例化。或者,从另一个角度看,我的片段->视图模型工厂->视图模型->存储库->DAO->实体 对于阵列适配器“适合”MVVM模式的位置,我有点困惑。该特定片段设计用于显示一组字段(名称、语言等),作为应用程序中的“配置文件”创建页面 问题: 我试图用语言列表填充微调器,这样当选择微调器中的语言时,软件中实际会使用相应的值(想想:文本-值对)。我真的不知道我在做什么,但我正在尽可能快地失败。目前,我在fragment onViewCreated方法中遇到以下错误: Android Studio错误:“无法解析“Observable”中的方法“observe” 代码 语言实体使用RxJava3在房间数据库的片段中填充微调器的问题,java,android,android-fragments,android-spinner,rx-java3,Java,Android,Android Fragments,Android Spinner,Rx Java3,概述 我正在尽力遵循MVVM模式。在我的数据模型中,我有一个实体“languages”及其通过存储库访问的对应DAO。这个存储库反过来为我的viewmodel提供信息,并通过片段中的工厂进行实例化。或者,从另一个角度看,我的片段->视图模型工厂->视图模型->存储库->DAO->实体 对于阵列适配器“适合”MVVM模式的位置,我有点困惑。该特定片段设计用于显示一组字段(名称、语言等),作为应用程序中的“配置文件”创建页面 问题: 我试图用语言列表填充微调器,这样当选择微调器中的语言时,软件中实际
@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;
}
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();
}
//...
}
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();
}
我尝试过的
我真的尝试过使用这里介绍的文本-值对功能:
(这让我摸不着头脑,为什么“观察”会引起问题)
使用此处显示的可观察机械:
…还有这里的ID内容(我已经对下面两个链接中的许多代码进行了注释,因为我还没走那么远):
和
经常困扰我的问题是,我无法遍历带有for-each循环的单个对象,因为当我将“语言”对象列表转换为“语言”对象列表时,“foreach未为RxJava定义…Single”(或类似的内容)
我以为我可以将语言对象作为单个对象检索,然后在.map或.flatMap函数中将它们添加到我的列表中,但这就是我的目的
问题
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, android.R.layout.simple_spinner_dropdown_item,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, View view, int position, 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.
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;
}
}