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

时间:2018-11-03 16:04:00

标签: android android-room observer-pattern android-architecture-components android-livedata

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

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

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

最后,JobIntentService通过LocalBroadcastManager将结果发送到托管Activity,然后该Activity在Fragment上调用public方法。

该路径有效,但是您可以看到它很长,我不得不编写许多样板代码来实现它。

最近我对Reddit有了一个提示,LiveData在这种情况下更好,我一直在阅读它,并已经切换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 个答案:

答案 0 :(得分:1)

我遵循了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;
    }