模型层(MVP)应该使用 Activity 引用

The model layer (MVP) should use the Activity reference

当模型中有一个操作需要当前 activity 实例时,如何在模型层和视图层之间进行适当的分离?

例如,我在我的 Android 应用程序中集成了 Linkedin SDK(用 MVP 编写)。 在 auth 过程中,当 init() 方法的第一个参数类型为 Activity:

时,我有以下代码片段
public void authWithLinkedin(final IAuth listener, Activity activity) {
    LISessionManager.getInstance(MyApplication.getContext()).init(activity, buildScope(), new AuthListener() {

        @Override
        public void onAuthSuccess() {
            listener.onSuccess();
        }

        @Override
        public void onAuthError(LIAuthError error) {
            listener.onError();
        }

    }, true);
}

如果我的模型层应该了解 Android 框架组件,我还有哪些选择可以保持 MVP 架构的清洁?

您可以使用像

这样的软件约定/原则

"dependency inversion principle"

"ports and adapters"

你的模型层应该知道Android如果你能避免它是重点。


尝试这样的事情:

型号:

private final SocialLoginProvider socialLoginProvider;

public MyModel(SocialLoginProvider socialLoginProvider) {
       this.socialLoginProvider = socialLoginProvider;
}

public void authWithLinkedin(final IAuth listener) {
       socialLoginProvider.init(buildScope(), new SocialLoginProvider.Listener() {

        @Override
        public void onAuthSuccess() {
            listener.onSuccess();
        }

        @Override
        public void onAuthError() {
            listener.onError();
        }

    }, true);
}

工厂:

public MyModel getModel(Context context) {
    LISessionManager li = LISessionManager.getInstance(context);
    SocialLoginProvider provider = new LinkedInSocialLoginProvider(context, li);
    return new MyModel(provider);
}

接口:

public interface SocialLoginProvider {
     void init(Scope scope, Listener listener);

     interface Listener {
           void onAuthSuccess();
           void onAuthError();
     } 
}

SocialLoginProvider 的适配器:

public class LinkedInSocialLoginProvider implements SocialLoginProvider {

          private final Context context;
          private final LISessionManager linkedInSessionManager;

          public LinkedInSocialLoginProvider(Context context, LISessionManager linkedInSessionManager) {
               this.context = context;
               this.linkedInSessionManager = linkedInSessionManager;
          }

          @Override
          public void init(Scope scope, Listener listener) {
              linkedInSessionManager.init(context, scope, 
                    new AuthListener() {
                      @Override
                      public void onAuthSuccess() {
                         listener.onSuccess();
                      }

                      @Override
                      public void onAuthError(LIAuthError error) {
                         listener.onError();
                      }
                   }, true);
           }

}

理想情况下,模型层中有 Android 个框架组件是可以的。例如,您将需要 Context 到 store/access 本地数据,使用 getDefaultSharedPreferences(Context) and/or 使用 SQLiteOpenHelper 管理本地数据库。

LISessionManager.getInstance(MyApplication.getContext()).init 看起来像 BroadcastReceiver,因为它是一种从外部组件接收特定结果的侦听器。处理这种情况可以参考this