1

How can I make a proper separation between the Model layer and the View layer, when I have an operation in the Model that needs the current activity instance?

For example, I've integrated Linkedin SDK in my Android app (written in MVP). In the auth process I have the following code snippet, when init() method's first argument type is 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);
}

If my Model layer should get to know Android framework components, what options do I have left to preserve the MVP architecture clean?

4

2 回答 2

1

您可以使用软件约定/原则,例如

“依赖倒置原则”

“端口和适配器”

如果你能避免它,你的模型层不应该知道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);
           }

}
于 2017-04-13T21:52:10.590 回答
0

理想情况下,模型层中有 Android 框架组件是可以的。例如,您将需要在Context本地存储/访问数据getDefaultSharedPreferences(Context)和/或使用SQLiteOpenHelper.

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

于 2017-04-13T22:01:36.533 回答