我有一个简单的Android应用程序。它有一个我可以触摸的全屏视图,并显示触摸。每3秒钟,所有触摸的数量(MotionEvents)和指针的总数量' (用于多点触控)显示3秒间隔。所有这些都是通过RxAndroid完成的。问题是,当我用10个手指敲击触摸屏时,我得到MissingBackpressureException
- 我猜这些事件对于订阅者而言产生得太快。我尝试添加onBackpressureDrop()
,但它并没有改变任何内容。我想我错过了一些至关重要的东西,但又是什么?
这是代码(我使用Retrolambda,所以不要对Android上的lambda感到困惑,这是可能的)。 RX部分为onCreate()
。
public class MainActivity extends Activity {
private ViewGroup viewGroup;
private TextView touchCountIndicator;
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
touchCountIndicator = (TextView) findViewById(R.id.touchCountIndicator);
PublishSubject<MotionEvent> touchPublishSubject = PublishSubject.create();
viewGroup = (ViewGroup) findViewById(android.R.id.content);
viewGroup.setOnTouchListener((v, event) -> {
touchPublishSubject.onNext(event);
return true;
});
ViewObservable
.bindView(viewGroup, touchPublishSubject)
.onBackpressureDrop()
.filter(motionEvent -> {
int action = motionEvent.getActionMasked();
return action == MotionEvent.ACTION_DOWN
|| action == MotionEvent.ACTION_POINTER_DOWN
|| action == MotionEvent.ACTION_MOVE;
})
.doOnNext(this::showTouch)
.map(motionEvent -> MotionEvent.obtain(motionEvent))
.buffer(3L, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::showTouchCount);
}
private void showTouch(MotionEvent motionEvent) {
for (int i = 0; i < motionEvent.getPointerCount(); ++i) {
float x = motionEvent.getX(i);
float y = motionEvent.getY(i);
ImageView touchIndicator = new ImageView(MainActivity.this);
touchIndicator.setImageResource(R.drawable.touch);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(10, 10);
params.leftMargin = (int) (x - 5);
params.topMargin = (int) (y - 5);
viewGroup.addView(touchIndicator, params);
touchIndicator
.animate()
.alpha(0F)
.scaleXBy(25F)
.scaleYBy(25F)
.setDuration(1000L)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
viewGroup.removeView(touchIndicator);
}
});
}
}
private void showTouchCount(List<MotionEvent> motionEvents) {
Observable
.from(motionEvents)
.doOnNext(MotionEvent::recycle)
.scan(0, (integer, motionEvent) -> integer + motionEvent.getPointerCount())
.last()
.subscribe(pointerCount -> {
touchCountIndicator.setText("" + motionEvents.size() + " " + pointerCount);
touchCountIndicator
.animate()
.alpha(0F)
.scaleXBy(15F)
.scaleYBy(15F)
.setDuration(1000L)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
touchCountIndicator.setText(null);
touchCountIndicator.setAlpha(1F);
touchCountIndicator.setScaleX(1F);
touchCountIndicator.setScaleY(1F);
}
});
});
}
}
XML布局:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.test.rxandroid.MainActivity">
<TextView
android:id="@+id/touchCountIndicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</FrameLayout>
使用的主题是&#39; android:Theme.Material.Light.NoActionBar.Fullscreen&#39; (我在5.1.1上)。
堆栈跟踪部分是:
Caused by: rx.exceptions.MissingBackpressureException
at rx.internal.util.RxRingBuffer.onNext(RxRingBuffer.java:338)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.onNext(OperatorObserveOn.java:115)
at rx.observers.SerializedObserver.onNext(SerializedObserver.java:159)
at rx.observers.SerializedSubscriber.onNext(SerializedSubscriber.java:81)
at rx.subjects.SubjectSubscriptionManager$SubjectObserver.onNext(SubjectSubscriptionManager.java:224)
at rx.subjects.PublishSubject.onNext(PublishSubject.java:121)
at com.test.rxandroid.MainActivity.lambda$onCreate$0(MainActivity.java:50)
...
答案 0 :(得分:1)
您必须在绑定前对主题应用onBackpressureDrop
运算符:
.bindView(viewGroup, touchPublishSubject.onBackpressureDrop()).filter(...)