android – 在onPause之后触发的OnClickListener?

前端之家收集整理的这篇文章主要介绍了android – 在onPause之后触发的OnClickListener?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用的项目使用视图展示器抽象.
这是所有主要类的简化版本.

抽象活动(Wire Presenter实例,带View)

  1. public abstract class MvpActivity<Presenter extends MvpPresenter>
  2. extends ActionBarActivity {
  3.  
  4. protected Presenter mPresenter;
  5.  
  6. @Override protected void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. mPresenter = getPresenterInstance();
  9. }
  10.  
  11. @Override protected void onResume() {
  12. super.onResume();
  13. mPresenter.onResume(this);
  14. }
  15.  
  16. @Override protected void onPause() {
  17. mPresenter.onPause();
  18. super.onPause();
  19. }
  20. }

视图界面

  1. public interface MyView {
  2. void redirect();
  3. }

视图实现

  1. public class MyActivity
  2. extends MvpActivity<MyPresenter>
  3. implements MyView {
  4.  
  5. @Override protected void onCreate(Bundle savedInstanceState) {
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.my_view);
  8.  
  9. Button myButton = (Button)findViewById(R.id.my_button);
  10.  
  11. myButton.setOnClickListener(v -> mPresenter.onButtonPressed());
  12. }
  13.  
  14. @Override protected MyPresenter getPresenterInstance() {
  15. return new MyPresenter();
  16. }
  17.  
  18. @Override void redirect(){
  19. startActivity(new Intent(this,MyOtherActivity.class));
  20. }

抽象的主持人

  1. public abstract class MvpPresenter<ViewType> {
  2.  
  3. private ViewType mView;
  4.  
  5. public void onResume(ViewType view) {
  6. mView = view;
  7. }
  8.  
  9. public void onPause() {
  10. mView = null;
  11. }
  12.  
  13. protected ViewType getView() {
  14. if (mView == null) {
  15. throw new IllegalStateException("Presenter view is null");
  16. }
  17. return mView;
  18. }
  19. }

和演示者实现

  1. public class MyPresenter extends MvpPresenter<MyView> {
  2.  
  3. @Override public void onResume(MyView myView){
  4. super.onResume(myView);
  5. Log.("MyPresenter","Presenter resumed");
  6. }
  7.  
  8. @Override public void onPause(){
  9. super.onPause()
  10. Log.("MyPresenter","Presenter paused");
  11. }
  12.  
  13. public void onButtonPressed(){
  14. getView().redirect();
  15. }
  16. }

问题出现在getView()触发的“IllegalStateException:Presenter视图为空”.redirect();从MyPresenter.onButtonPressed()方法调用时.

这对我没有任何意义,因为如果侦听器被触发,视图应始终不为null.如果执行仅从MvpActivity.onPause()调用的MvpPresenter.onPause(),则视图仅设置为null.发生这种情况后,我不希望收到任何点击事件,所以我在这里缺少什么?

遗憾的是,我无法通过手动测试应用程序来重现此问题.这些报道来自Crashlytics.

注意:retrolambda用于按钮单击侦听器

更新10/07/2017

解决此问题的一些方法


https://developer.android.com/reference/android/view/View.html#cancelPendingInputEvents()


https://github.com/JakeWharton/butterknife/blob/master/butterknife/src/main/java/butterknife/internal/DebouncingOnClickListener.java

解决方法

简短的回答:不要这样做.

不幸的是,您依赖的是未定义的事件顺序.活动生命周期事件和窗口事件是两个不同的事情,即使它们通常密切相关.当活动因任何原因暂停时,您将获得onPause().但View视图窗口失去焦点后,View触摸事件不会被取消.

当一个活动窗口失去焦点时,例如当屏幕被锁定或启动另一个活动时,它就会非常常见.但正如您所见,您可以在没有焦点变化的情况下暂停,并且可以不停顿地进行焦点更改.即使两个事件一起发生,当调用onPause()但窗口输入处理程序仍处于活动状态时,会有一个很窄的时间窗口.

与任何未定义的行为一样,您看到的实际结果将因操作系统版本和硬件类型而异.

如果您需要确保在onPause之后没有收到View消息,则应该在onPause中取消挂钩处理程序.

猜你在找的Android相关文章