首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与活动生命周期挂钩的第三方库的灰浆+流

与活动生命周期挂钩的第三方库的灰浆+流
EN

Stack Overflow用户
提问于 2014-02-21 07:27:33
回答 2查看 3K关注 0票数 16

一些第三方库使用活动生命周期中的钩子来正确工作--例如,Facebook (https://developers.facebook.com/docs/android/login-with-facebook/)。

我在弄清楚如何将该模型与单个活动的flow+mortar设置进行协调时遇到了一些困难。

例如,如果我想使用Facebook登录作为登录流(w/ FlowView/FlowOwner)的一部分,但在活动中不使用其他方式,那么如果您需要为onCreate、onResume、onPause、onDestroy、onSaveInstanceState、onActivityResult等中的特定流提供挂钩,那么最聪明的方法是什么呢?

现在还不清楚什么是最干净的路径--为每个生命周期活动阶段创建一个可观察的,并订阅它的流程?如果你不小心的话,这条路似乎很快就会转移到相同的Android生命周期。有更好的办法吗?

我喜欢单一的活动模型,如果可能的话,我很想让所有的事情都由流/迫击炮来管理,而不是活动。还是我在考虑这件事,从根本上说,这比应该做的更困难?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-31 17:13:14

到目前为止,我们还没有开始和停止的需要,但确实有一些需要暂停和恢复的地方。我们按照您的建议使用ActivityPresenter,但避免使用任何类型的通用超类。相反,它公开了感兴趣的演讲者可以选择的服务。这种连接需要是添加onEnterScope(Scope)方法的原因。这是密码。

首先,让活动实现这个接口:

代码语言:javascript
复制
/**
 * Implemented by {@link android.app.Activity} instances whose pause / resume state
 * is to be shared. The activity must call {@link PauseAndResumePresenter#activityPaused()}
 * and {@link PauseAndResumePresenter#activityResumed()} at the obvious times.
 */
public interface PauseAndResumeActivity {
  boolean isRunning();

  MortarScope getMortarScope();
}

并让它注射推荐人并打适当的电话:

代码语言:javascript
复制
private boolean resumed;
@Inject PauseAndResumePresenter pauseNarcPresenter;

@Override protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  pauseNarcPresenter.takeView(this);
}

@Override public boolean isRunning() {
  return resumed;
}

@Override protected void onResume() {
  super.onResume();
  resumed = true;
  pauseNarcPresenter.activityResumed();
}

@Override protected void onPause() {
  resumed = false;
  super.onPause();
  pauseNarcPresenter.activityPaused();
}

@Override protected void onDestroy() {
  pauseNarcPresenter.dropView(this);
  super.onDestroy();
}

现在,感兴趣的各方可以插入一个注册员接口,以选择暂停和恢复调用,而无需对任何内容进行子类划分。

代码语言:javascript
复制
/**
 * Provides means to listen for {@link android.app.Activity#onPause()} and {@link
 * android.app.Activity#onResume()}.
 */
public interface PauseAndResumeRegistrar {
  /**
   * <p>Registers a {@link PausesAndResumes} client for the duration of the given {@link
   * MortarScope}. This method is debounced, redundant calls are safe.
   *
   * <p>Calls {@link PausesAndResumes#onResume()} immediately if the host {@link
   * android.app.Activity} is currently running.
   */
  void register(MortarScope scope, PausesAndResumes listener);

  /** Returns {@code true} if called between resume and pause. {@code false} otherwise. */
  boolean isRunning();
}

让客户端演示者实现此接口:

代码语言:javascript
复制
/**
 * <p>Implemented by objects that need to know when the {@link android.app.Activity} pauses
 * and resumes. Sign up for service via {@link PauseAndResumeRegistrar#register(PausesAndResumes)}.
 *
 * <p>Registered objects will also be subscribed to the {@link com.squareup.otto.OttoBus}
 * only while the activity is running.
 */
public interface PausesAndResumes {
  void onResume();

  void onPause();
}

把事情搞成这样。(请注意,无需注销。)

代码语言:javascript
复制
private final PauseAndResumeRegistrar pauseAndResumeRegistrar;

@Inject
public Presenter(PauseAndResumeRegistrar pauseAndResumeRegistrar) {
  this.pauseAndResumeRegistrar = pauseAndResumeRegistrar;
}

@Override protected void onEnterScope(MortarScope scope) {
  pauseAndResumeRegistrar.register(scope, this);
}

@Override public void onResume() {
}

@Override public void onPause() {
}

下面是活动注入的演示者,以使其全部正常工作。

代码语言:javascript
复制
/**
 * Presenter to be registered by the {@link PauseAndResumeActivity}.
 */
public class PauseAndResumePresenter extends Presenter<PauseAndResumeActivity>
    implements PauseAndResumeRegistrar {

  private final Set<Registration> registrations = new HashSet<>();

  PauseAndResumePresenter() {
  }

  @Override protected MortarScope extractScope(PauseAndResumeActivity view) {
    return view.getMortarScope();
  }

  @Override public void onExitScope() {
    registrations.clear();
  }

  @Override public void register(MortarScope scope, PausesAndResumes listener) {
    Registration registration = new Registration(listener);
    scope.register(registration);

    boolean added = registrations.add(registration);
    if (added && isRunning()) {
      listener.onResume();
    }
  }

  @Override public boolean isRunning() {
    return getView() != null && getView().isRunning();
  }

  public void activityPaused() {
    for (Registration registration : registrations) {
      registration.registrant.onPause();
    }
  }

  public void activityResumed() {
    for (Registration registration : registrations) {
      registration.registrant.onResume();
    }
  }

  private class Registration implements Scoped {
    final PausesAndResumes registrant;

    private Registration(PausesAndResumes registrant) {
      this.registrant = registrant;
    }

    @Override public void onEnterScope(MortarScope scope) {
    }

    @Override public void onExitScope() {
      registrations.remove(this);
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      Registration that = (Registration) o;

      return registrant.equals(that.registrant);
    }

    @Override
    public int hashCode() {
      return registrant.hashCode();
    }
  }
}
票数 13
EN

Stack Overflow用户

发布于 2014-02-22 19:43:33

因此,我一直在移植一个个人应用程序的流程和迫击性,以评估它的商业用途。我还没有遇到一个必须拥有整个活动生命周期的场景,但就当前的flow (v0.4)和迫击炮(v0.7)版本而言,我认为您必须自己创造性地解决这个问题。我已经意识到这对我自己来说是一个潜在的问题,并思考了如何克服这个问题:

我也想指出,我还没有真正使用过Facebook。你必须为自己选择最好的方法。

  1. 您可以为每个活动生命周期事件发布活动中的事件。实际上,您提到了使用RXJava的可观测值的这种方法。如果您真的想使用RXJava,您可以使用PublishSubject进行此操作,但我可能会使用您可以订阅的EventBus中的简单事件。这可能是最简单的方法。
  2. 您还可以根据Facebook的工作方式,在活动中注入Facebook组件,然后从那里初始化它。然后将Facebook组件注入要使用的视图中。流和砂浆的整个系统到底是深深地集成到依赖注入吗?这种方法也相当简单,但取决于Facebook的工作方式,它可能不是最好的选择。如果你真的走了这条路,你需要注意我在这篇文章的底部发出的警告。
  3. 这就是我的最后一个想法。Square在需要访问活动的子视图/演示程序中的ActionBar时也遇到了类似的问题。他们在他们的示例应用程序中公开了对ActionBar的访问,这是通过他们所称的ActionBarOwner.java进行的。然后他们实现了ActionBarOwner接口,并在DemoActivity.java中给出了自己的一个实例。如果您研究他们是如何实现的,并通过注入来共享它,您可以创建一个类似的类。AcivityLifecycleOwner或其他什么东西(名称需要工作),您可以订阅来自演示者的回调。如果你决定沿着这条路走,而且不小心,你很容易就会导致内存泄漏。无论何时您要订阅任何事件(我建议您在演示者中订阅),您也需要确保在onDestroy方法中取消订阅。我创建了一个简短的未经测试的示例,说明了下面这个解决方案的含义。

无论您使用哪种方法,您都可能需要确保您的onCreate和onDestroy方法实际上来自您的演示者,而不是活动中的确切事件。如果您只在单个视图上使用sdk,则在视图实例化之前很久就已经调用了该活动的onCreate,并且在视图被销毁后将调用该活动的onDestroy。我认为演示者的onLoad和onDestroy应该足够了,但是我还没有测试这个。

祝你好运!

未测试的解决方案3:的代码示例

所有演示者都可以扩展这个类,而不是ViewPresenter,然后就像在一个活动中一样,覆盖每个您想要的事件的方法:

代码语言:javascript
复制
public abstract class ActivityLifecycleViewPresenter<V extends View> extends ViewPresenter<V>
    implements ActivityLifecycleListener {

  @Inject ActivityLifecycleOwner mActivityLifecycleOwner;

  @Override protected void onLoad(Bundle savedInstanceState) {
    super.onLoad(savedInstanceState);
    mActivityLifecycleOwner.register(this);
  }

  @Override protected void onDestroy() {
    super.onDestroy();
    mActivityLifecycleOwner.unregister(this);
  }

  @Override public void onActivityResume() {
  }

  @Override public void onActivityPause() {
  }

  @Override public void onActivityStart() {
  }

  @Override public void onActivityStop() {
  }

}

活动生命周期所有者,它将被注入到活动中,然后连接到相应的事件。我故意不包括onCreate和onDestroy,因为你的主持人将无法访问这些事件,因为它们不会被创建或者已经被销毁。您需要使用演示文者onLoad和onDestroy方法来代替这些方法。也有可能其他一些事件不会被调用。

代码语言:javascript
复制
public class ActivityLifecycleOwner implements ActivityLifecycleListener {

  private List<ActivityLifecycleListener> mRegisteredListeners
      = new ArrayList<ActivityLifecycleListener>();

  public void register(ActivityLifecycleListener listener) {
    mRegisteredListeners.add(listener);
  }

  public void unregister(ActivityLifecycleListener listener) {
    mRegisteredListeners.remove(listener);
  }

  @Override public void onActivityResume() {
    for (ActivityLifecycleListener c : mRegisteredListeners) {
      c.onActivityResume();
    }
  }

  @Override public void onActivityPause() {
    for (ActivityLifecycleListener c : mRegisteredListeners) {
      c.onActivityPause();
    }
  }

  @Override public void onActivityStart() {
    for (ActivityLifecycleListener c : mRegisteredListeners) {
      c.onActivityStart();
    }
  }

  @Override public void onActivityStop() {
    for (ActivityLifecycleListener c : mRegisteredListeners) {
      c.onActivityStop();
    }
  }
}

现在,您需要将生命周期所有者与活动挂钩:

代码语言:javascript
复制
public class ActivityLifecycleExample extends MortarActivity {

  @Inject ActivityLifecycleOwner mActivityLifecycleOwner;

  @Override protected void onResume() {
    super.onResume();
    mActivityLifecycleOwner.onActivityResume();
  }

  @Override protected void onPause() {
    super.onPause();
    mActivityLifecycleOwner.onActivityPause();
  }

  @Override protected void onStart() {
    super.onStart();
    mActivityLifecycleOwner.onActivityStart();
  }

  @Override protected void onStop() {
    super.onStart();
    mActivityLifecycleOwner.onActivityStop();
  }

}
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21927990

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档