2016-05-17 22 views
0

我剛剛開始一個新的示例項目來測試與莫斯比指揮。 問題是,在我離開FirstScreen或旋轉設備後,在Rx onNext回調之後,isViewAttached()總是返回false,我不明白爲什麼。 一些片段澄清:莫斯比,指揮和Rx打得不好

public abstract class MvpLceRxPresenter<V extends MvpLceView<M>, M> extends MvpBasePresenter<V> 
     implements MvpPresenter<V> { 

    protected Subscriber<M> subscriber; 

    protected void unsubscribe() { 
     if (subscriber != null && !subscriber.isUnsubscribed()) { 
      subscriber.unsubscribe(); 
     } 

     subscriber = null; 
    } 

    public void subscribe(@NonNull UseCase useCase, @Nullable Bundle bundle, final boolean pullToRefresh) { 
     if (isViewAttached()) { 
      getView().showLoading(pullToRefresh); 
     } 

     useCase.unsubscribe(); 

     subscriber = new Subscriber<M>() { 
      private boolean ptr = pullToRefresh; 

      @Override 
      public void onCompleted() { 
       MvpLceRxPresenter.this.onCompleted(); 
      } 

      @Override 
      public void onError(Throwable e) { 
       MvpLceRxPresenter.this.onError(e, ptr); 
      } 

      @Override 
      public void onNext(M m) { 
       MvpLceRxPresenter.this.onNext(m); 
      } 
     }; 

     if (useCase instanceof DynamicUseCase) { 
      DynamicUseCase dynamicUseCase = (DynamicUseCase) useCase; 
      dynamicUseCase.execute(subscriber, bundle); 
     } else { 
      useCase.execute(subscriber); 
     } 
    } 

    public void subscribe(Observable<M> observable, final boolean pullToRefresh) { 
     if (isViewAttached()) { 
      getView().showLoading(pullToRefresh); 
     } 

     unsubscribe(); 

     subscriber = new Subscriber<M>() { 
      private boolean ptr = pullToRefresh; 

      @Override 
      public void onCompleted() { 
       MvpLceRxPresenter.this.onCompleted(); 
      } 

      @Override 
      public void onError(Throwable e) { 
       MvpLceRxPresenter.this.onError(e, ptr); 
      } 

      @Override 
      public void onNext(M m) { 
       MvpLceRxPresenter.this.onNext(m); 
      } 
     }; 

     observable.subscribeOn(Schedulers.io()) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(subscriber); 

    } 

    protected void onCompleted() { 
     if (isViewAttached()) 
      getView().showContent(); 
     unsubscribe(); 
    } 

    protected void onError(Throwable e, boolean pullToRefresh) { 
     if (isViewAttached()) 
      getView().showError(e, pullToRefresh); 
     unsubscribe(); 
    } 

    protected void onNext(M data) { 
     if (isViewAttached()) 
      getView().setData(data); 
    } 

    @Override 
    public void detachView(boolean retainInstance) { 
     super.detachView(retainInstance); 
     if (!retainInstance) 
      unsubscribe(); 
    } 

我主持人:

@DaggerScope(FirstScreenComponent.class) 
public class FirstScreenPresenter extends MvpLceRxPresenter<FirstView, List<Contact>> { 

    private final GetContacts getContacts; 

    @Inject 
    public FirstScreenPresenter(GetContacts getContacts) { 
     this.getContacts = getContacts; 
    } 

    public void fetchContacts(boolean mustHaveNumber) { 
     Bundle bundle = new Bundle(1); 
     bundle.putBoolean("mustHaveNumber", mustHaveNumber); 

     subscribe(this.getContacts, bundle, false); 
    } 
} 

而且FirstScreen的某些部分:

@Override 
    public void onPrepareOptionsMenu(Menu menu) { 
     super.onPrepareOptionsMenu(menu); 
     swapNumberOnlyText(menu.findItem(R.id.number_only)); 
    } 

    private void swapNumberOnlyText(MenuItem item) { 
     if(mustHaveNumber) 
      item.setTitle("Todos contatos"); 
     else 
      item.setTitle("Somente com número"); 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 

     if(item.getItemId() == R.id.number_only){ 
      mustHaveNumber = !mustHaveNumber; 
      this.presenter.fetchContacts(mustHaveNumber); 
      swapNumberOnlyText(item); 
      return true; 
     } 

     return super.onOptionsItemSelected(item); 
    } 
@Override 
    public List<Contact> getData() { 
     return adapter.getContacts(); 
    } 

    @Override 
    public void setData(List<Contact> data) { 
     adapter.setContacts(data); 
    } 

    @Override 
    protected String getErrorMessage(Throwable e, boolean pullToRefresh) { 
     return null; 
    } 

    @NonNull 
    @Override 
    public LceViewState<List<Contact>, FirstView> createViewState() { 
     return new RetainingLceViewState<>(); 
    } 

    @NonNull 
    @Override 
    public FirstScreenPresenter createPresenter() { 
     return presenter; 
    } 

    @Override 
    public void loadData(boolean pullToRefresh) { 
     this.presenter.fetchContacts(mustHaveNumber); 
    } 

什麼是竊聽我是第一次打開時,我可以點擊在菜單項上,它的功能就像一個魅力,但是如果我離開或旋轉,所描述的問題就開始了。

任何幫助將不勝感激!

+0

只爲其他人盯着同一個問題:一些描述的行爲是所需的,屏幕方向問題可能是一個錯誤。見https://github.com/sockeqwe/mosby/issues/136 我會在這裏發佈最終解決方案 – sockeqwe

回答

3

這不是一個Mosby-Conductor問題。這個問題是由匕首和注入演示者的方式造成的。

您正在爲onViewBound()方法的每個屏幕方向更改創建並注入新的Presenter實例。這意味着每個屏幕方向都會創建一個新的演示者。

此外,由於您正在爲演示者聲明自己的字段,因此對Presenter沒有使用MvpLceViewStateController字段。請參閱:https://github.com/sockeqwe/mosby-conductor/blob/master/mvp/src/main/java/com/hannesdorfmann/mosby/mvp/conductor/MvpController.java#L19

莫斯內部工作原理如下:

if (getPresenter() == null) { 
    setPresenter( createPresenter()); 
} 

在MvpController(基類MvpViewStateLceController您是從getPresenter()和setPresenter()延長使用MvpController.presenter場 https://github.com/sockeqwe/mosby-conductor/blob/master/mvp/src/main/java/com/hannesdorfmann/mosby/mvp/conductor/MvpController.java#L19

有兩個解決方案:

  1. 不要聲明你[R自己的演講現場,而是做這樣的事情(它將使用MvpController.presenter場):

    @覆蓋 公共FirstScreenPresenter createPresenter(){ 回報DaggerFirstScreenComponent.builder() .activityComponent(((RootActivity)getActivity ())。getActivityComponent()) .firstScreenModule(new FirstScreenModule()) .build()。presenter(); }

這確保了演示實例將自createPresenter創建僅一次()將只調用一次。

  • 如果你想使用自己的現場演示,那麼你也有你的控制器,從MvpLce

    公共類FirstScreen延伸到覆蓋setPresenter()和getPresenter()延伸BaseController,的firstView,FirstScreenPresenter>實現的firstView {

    private static final String MUST_HAVE_NUMBER = "must_have_number"; 
    @Inject 
    protected FirstScreenPresenter presenter; 
    

    @Override 公共FirstScreenPresenter getPresenter(){ 返回演示; }

    @Override 
    public void setPresenter(FirstScreenPresenter p){ 
        this.presenter = p; 
    } 
    
  • 的,因爲這樣莫斯內部工作調用getPresenter(),createPresenter()和setPresenter()。但是,仍然必須確保不要在onViewBound()方法中創建並注入新的Presenter。

    Btw。你也可以遇到這個問題,如果你使用活動/碎片莫斯比而不是導體