RxJava - 如何在 Android 中的 4 个点击事件中调用订阅者
RxJava - how to invoke subscriber on 4 click events in Android
在 android 中,我有一个这样定义的文本视图:
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
android:textColorHighlight="#000000"
android:textIsSelectable="true" />
我的目标是点击4次后,我想重新开始activity。我需要用 RXJava 来做这件事;这是一个要求。或 rxAndroid
、rxBinding
等
我的 activity 看起来像这样:
public class MainActivity extends Activity implements onClickListener {
TextView tv;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)findViewById(R.id.text1);
tv.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if(v.getId() == R.id.text1){
}
}
}
更新:
但这只是标准的做法。必须有一种方法来处理反应式 rxJava API。
所以不用 onClicklistener
和 rxBinding
我读过我们可以这样做:
RxView.clicks(tv).flatMap(tv -> {
// another observable which can throw onError.
return Observable.error(null);
}).subscribe(object -> {
Log.d("CLICK", "textview clicked", start activity);
}, error -> {
Log.d("CLICK", "ERROR");
});
我能否以某种方式使用 rxBinding
中的命令使其仅在单击 4 次后执行?我不想存储静态变量,或使用匿名 class 并在其中存储成员变量以进行计数。为此应该有一个可观察的方法。
您可以创建一个 observable 以在每次单击按钮时发出,然后计算它发出的总次数,并使用过滤器以便您的订阅者只能在它发出四次后看到它。
Observable<View> buttonObservable = ViewObservable.clicks(initiateButton, false);
buttonObservable.count()
.filter(count -> (count >= 4))
.subscribe(object -> {
//Your code here
});
你可以这样实现:
Observable.create((Observable.OnSubscribe<Void>) subscriber -> {
if (!subscriber.isUnsubscribed()) {
button.setOnClickListener(v -> subscriber.onNext(null));
}
}).buffer(1000, TimeUnit.MILLISECONDS)
.filter(clicks -> clicks.size() == 4)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(clicks -> {
Log.d("CLICK", "CLICK");
});
buffer()
- 收集点击 1 秒 window
filter()
- 过滤所有发出的缓冲项,其中缓冲区中的项数不等于 4(禁用双击、三次、五次点击)
最难的部分是指定缓冲时间"window"。一秒有时是不够的,但在其他情况下用户必须等待几毫秒。
@skywall 的答案是最完整的,但是如果您不关心时间间隔,最简单的答案是使用 skip
Observable<Void> fourClicksView = RxView.clicks(tv).skip(3);
fourClicksView.subscribe(...);
如果您想在一段时间 window 内点击一定次数后开始 activity,请试试这个:
RxView.clicks(tv)
.map(e -> SystemClock.elapsedRealtime())
.buffer(NUM_CLICKS, 1) //Grab every sub-sequence of however many clicks
.filter(times -> times.size() == NUM_CLICKS) //Last values will be truncated
.filter(times -> times.get(NUM_CLICKS - 1) - times.get(0) < ALLOWED_TIME) //check times
.subscribe(ignore -> startActivity());
使用缓冲和去抖运算符。
val clickStream = RxView.clicks(view)
clickStream.buffer(clickStream.debounce(250, TimeUnit.MILLISECONDS))
.map { it.size }
.filter { it == 4 }
.subscribe({
})
为了检测具有合理超时的多次点击(例如 1000 毫秒内的 4 次点击),以下方法效果很好:
final int numClicks = 4;
final int timeout = 1000;
disposables.add(RxView.clicks(tv)
.buffer(timeout, TimeUnit.MILLISECONDS, numClicks)
.filter(list -> list.size() == numClicks)
.subscribe(this::doThing));
在此示例中,buffer
将发出 4 个事件,或者每 1000 毫秒发出少于 4 个事件,由于 filter
将被忽略
在 android 中,我有一个这样定义的文本视图:
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
android:textColorHighlight="#000000"
android:textIsSelectable="true" />
我的目标是点击4次后,我想重新开始activity。我需要用 RXJava 来做这件事;这是一个要求。或 rxAndroid
、rxBinding
等
我的 activity 看起来像这样:
public class MainActivity extends Activity implements onClickListener {
TextView tv;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)findViewById(R.id.text1);
tv.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if(v.getId() == R.id.text1){
}
}
}
更新: 但这只是标准的做法。必须有一种方法来处理反应式 rxJava API。
所以不用 onClicklistener
和 rxBinding
我读过我们可以这样做:
RxView.clicks(tv).flatMap(tv -> {
// another observable which can throw onError.
return Observable.error(null);
}).subscribe(object -> {
Log.d("CLICK", "textview clicked", start activity);
}, error -> {
Log.d("CLICK", "ERROR");
});
我能否以某种方式使用 rxBinding
中的命令使其仅在单击 4 次后执行?我不想存储静态变量,或使用匿名 class 并在其中存储成员变量以进行计数。为此应该有一个可观察的方法。
您可以创建一个 observable 以在每次单击按钮时发出,然后计算它发出的总次数,并使用过滤器以便您的订阅者只能在它发出四次后看到它。
Observable<View> buttonObservable = ViewObservable.clicks(initiateButton, false);
buttonObservable.count()
.filter(count -> (count >= 4))
.subscribe(object -> {
//Your code here
});
你可以这样实现:
Observable.create((Observable.OnSubscribe<Void>) subscriber -> {
if (!subscriber.isUnsubscribed()) {
button.setOnClickListener(v -> subscriber.onNext(null));
}
}).buffer(1000, TimeUnit.MILLISECONDS)
.filter(clicks -> clicks.size() == 4)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(clicks -> {
Log.d("CLICK", "CLICK");
});
buffer()
- 收集点击 1 秒 windowfilter()
- 过滤所有发出的缓冲项,其中缓冲区中的项数不等于 4(禁用双击、三次、五次点击)
最难的部分是指定缓冲时间"window"。一秒有时是不够的,但在其他情况下用户必须等待几毫秒。
@skywall 的答案是最完整的,但是如果您不关心时间间隔,最简单的答案是使用 skip
Observable<Void> fourClicksView = RxView.clicks(tv).skip(3);
fourClicksView.subscribe(...);
如果您想在一段时间 window 内点击一定次数后开始 activity,请试试这个:
RxView.clicks(tv)
.map(e -> SystemClock.elapsedRealtime())
.buffer(NUM_CLICKS, 1) //Grab every sub-sequence of however many clicks
.filter(times -> times.size() == NUM_CLICKS) //Last values will be truncated
.filter(times -> times.get(NUM_CLICKS - 1) - times.get(0) < ALLOWED_TIME) //check times
.subscribe(ignore -> startActivity());
使用缓冲和去抖运算符。
val clickStream = RxView.clicks(view)
clickStream.buffer(clickStream.debounce(250, TimeUnit.MILLISECONDS))
.map { it.size }
.filter { it == 4 }
.subscribe({
})
为了检测具有合理超时的多次点击(例如 1000 毫秒内的 4 次点击),以下方法效果很好:
final int numClicks = 4;
final int timeout = 1000;
disposables.add(RxView.clicks(tv)
.buffer(timeout, TimeUnit.MILLISECONDS, numClicks)
.filter(list -> list.size() == numClicks)
.subscribe(this::doThing));
在此示例中,buffer
将发出 4 个事件,或者每 1000 毫秒发出少于 4 个事件,由于 filter