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?
You can use software conventions / principles like
"dependency inversion principle"
Your model layer should not know about Android if you can avoid it is the point.
Try something like this:
Model:
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);
}
Factory:
public MyModel getModel(Context context) {
LISessionManager li = LISessionManager.getInstance(context);
SocialLoginProvider provider = new LinkedInSocialLoginProvider(context, li);
return new MyModel(provider);
}
Interface:
public interface SocialLoginProvider {
void init(Scope scope, Listener listener);
interface Listener {
void onAuthSuccess();
void onAuthError();
}
}
Adapter for 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);
}
}