代码之家  ›  专栏  ›  技术社区  ›  Alexander Farber

当DAO方法需要改变参数时,如何使用LiveData?

  •  0
  • Alexander Farber  · 技术社区  · 6 年前

    在使用Room存储单词的字典应用程序中,我有一个带有TextField的片段。

    当用户在TextField中输入一个单词时,我提取文本并将其发送给JobIntentService,然后它在自己的线程上同步调用DAO方法:

    @Dao
    public interface MyDao {
        @Query("SELECT 1 FROM dictionary WHERE word = :word")
        int findWord(String word);
    }
    

    最后,JobIntentService通过LocalBroadcastManager将结果发送给宿主活动,该活动调用片段上的公共方法。

    这条路径是可行的,但是您可以看到它非常长,我必须编写很多样板代码来实现它。

    some of my fragments

    因此,我尝试将此片段也转换为使用LiveData,将方法的签名更改为:

    @Dao
    public interface MyDao {
        @Query("SELECT 1 FROM dictionary WHERE word = :word")
        LiveData<Integer> findWord(String word);
    }
    

    从我的片段中调用它:

    public class MyFragment extends Fragment {
        private static final Pattern PATTERN = Pattern.compile("([A-Z]{2,})");
    
        private LiveData<Integer> mLiveData;
    
        private EditText mInputText;
        private CheckedTextView mResultText;
    
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater,
                                 ViewGroup container,
                                 Bundle savedInstanceState) {
            ...
            mInputText.addTextChangedListener(new TextWatcher() {
                ...
                @Override
                public void afterTextChanged(Editable s) {
                    String word = mInputText.getText().toString().trim().toUpperCase();
                    if (PATTERN.matcher(word).matches()) {
                        mLiveData = MyDatabase.getInstance(getContext()).myDao().findWord(word);
                    } else {
                        mResultText.setChecked(false);
                    }
                }
            });
    
            mLiveData.observe(this, found -> {
                if (found != null && found == 1) {
                    mResultText.setChecked(true);
                } else {
                    mResultText.setChecked(false);
                }
            });
    
            return view;
        }
    

    当然,上述方法在NPE中失败了,因为 mLiveData 为空。

    但是当单词参数 findWord(word) 正在改变?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Alexander Farber    6 年前

    我听了pskink的暗示(谢谢!)以下几点似乎对我有用:

    public class MyFragment extends Fragment {
        private static final Pattern PATTERN = Pattern.compile("([A-Z]{2,})");
    
        private MutableLiveData<String> mTrigger = new MutableLiveData<>();
        private LiveData<Integer> mResult = Transformations.switchMap(mTrigger, 
            word -> MyDatabase.getInstance(getContext()).myDao().findWord(word));
    
        private EditText mInputText;
        private CheckedTextView mResultText;
    
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater,
                                 ViewGroup container,
                                 Bundle savedInstanceState) {
            ...
            mInputText.addTextChangedListener(new TextWatcher() {
                ...
                @Override
                public void afterTextChanged(Editable s) {
                    String word = mInputText.getText().toString().trim().toUpperCase();
                    if (PATTERN.matcher(word).matches()) {
                        mTrigger.setValue(word);
                    } else {
                        mResultText.setChecked(false);
                    }
                }
            });
    
            mLiveData.observe(this, found -> {
                if (found != null && found == 1) {
                    mResultText.setChecked(true);
                } else {
                    mResultText.setChecked(false);
                }
            });
    
            return view;
        }