0

当我单击一个按钮时,我正在尝试使用 RxJava 对 EditText 执行验证,但我很难将验证移至 ViewModel,这将使测试变得更加容易。我正在使用来自 Jake Wharton 的 RxBindings 来获取 UI 输入,并使用带有 PublishSubject 的 RxJava2 的 Flowable.combineLatest 在我单击 AlertDialog 上的按钮时触发 Flowable。这是我到目前为止得到的:

private Flowable<CharSequence> projectTitleObservable;
private final PublishSubject<CharSequence> createProjectClicked = PublishSubject.create();

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    final Context context = getActivity();

    View dialogView = LayoutInflater.from(context).inflate(R.layout.new_project, null);

    ButterKnife.bind(this, dialogView);

    projectTitleObservable = RxTextView.textChanges(projectNameEditText).toFlowable(BackpressureStrategy.LATEST);

    ConnectableFlowable <CharSequence> connectableFlowable = Flowable.combineLatest(createProjectClicked.toFlowable(BackpressureStrategy.LATEST), projectTitleObservable, (ignored, title) -> {
        boolean validTitle = !TextUtils.isEmpty(title);
        if (!validTitle) {
            projectNameEditText.setError("Project must have a name");
        }

        Timber.d("Hey, lambdas work! Look -> " + title);
        return title;
    })
            .publish();

    connectableFlowable.subscribe(test -> Timber.d(test.toString()));

    return new AlertDialog.Builder(context)
            .setTitle("Add new Project")
            .setView(dialogView)
            .setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
                Timber.d("Ok clicked!");
                createProjectClicked.onNext("It works!");
            })
            .setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> Timber.d("Cancel clicked!"))
            .create();
}

我只是在同一个地方发布和订阅,以确保它在将 ConnectableFlowable 移动到 ViewModel 之前确实有效。我得到的唯一日志是“确定点击!” 这对我来说意味着它从未被订阅过。关于为什么不订阅的任何想法?

4

2 回答 2

0

爪哇版:

如果代码有效,则显示 Toast:

private Observable<TextViewTextChangeEvent> taskTitleObservable;
private final PublishSubject<Boolean> createTaskClicked = PublishSubject.create();

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ButterKnife.bind(this, view);

    taskTitleObservable = RxTextView.textChangeEvents(taskTitle)
    .filter(event -> validateText(event.text().toString()));

    createTaskClicked.flatMap(test -> taskTitleObservable).subscribe( aVoid -> {
        Toast.makeText(getActivity(), "Text is correct", Toast.LENGTH_SHORT).show();
    });

    RxView.clicks(fab).subscribe(aVoid -> {
        createTaskClicked.onNext(true);
    });
}

private Boolean validateText (String text) {
    return text.length() >= 5;
}

文字不正确的反馈:

private Observable<Boolean> taskTitleObservable;
private final PublishSubject<Boolean> createTaskClicked = PublishSubject.create();

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ButterKnife.bind(this, view);

    taskTitleObservable = RxTextView.textChangeEvents(taskTitle)
            .map(event -> validateText(event.text().toString()));

    createTaskClicked.flatMap(test -> taskTitleObservable).subscribe( isTextCorrect -> {
        if (isTextCorrect) {
            Toast.makeText(getActivity(), "Text is correct", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(getActivity(), "Text is incorrect", Toast.LENGTH_SHORT).show();
        }
    });

    RxView.clicks(fab).subscribe(aVoid -> {
        createTaskClicked.onNext(true);
    });
}

private Boolean validateText (String text) {
    return text.length() >= 5;
}
于 2017-10-24T21:46:51.117 回答
0

我可以使用 flatMap 实现这种行为。以下是文本有效时如何显示 Toast 的示例:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val btnSubject = PublishSubject.create<Boolean>()
    val textObservable = RxTextView.textChangeEvents(editText)
            .filter { validateText(it.text().toString()) }

    btnSubject.flatMap { textObservable }
            .subscribe({
                Toast.makeText(this, "Text is correct", Toast.LENGTH_SHORT).show()
            })


    btn.setOnClickListener {
        btnSubject.onNext(true)
    }
}

private fun validateText(text: String) = text.length >= 5

如果您需要在文本不正确时显示一些反馈,您可以更改地图的过滤器并像这样使用它:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val btnSubject = PublishSubject.create<Boolean>()
    val textObservable = RxTextView.textChangeEvents(editText)
            .map { validateText(it.text().toString()) }

    btnSubject.flatMap { textObservable }
            .subscribe({ isTextCorrect ->
                if (isTextCorrect) {
                    Toast.makeText(this, "Text is correct", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(this, "Text NOT is correct", Toast.LENGTH_SHORT).show()
                }
            })


    btn.setOnClickListener {
        btnSubject.onNext(true)
    }
}

private fun validateText(text: String) = text.length >= 5

我刚刚测试了这段代码,工作得很好。

快乐的代码!

于 2017-10-24T16:16:33.510 回答