Open

Description
Introduction:
At the data layer
I have retrofit-interface. For example:
public interface SomeApi {
@POST(...)
Observable login(LoginRequest body);
}
At the domain layer
I have AccountManger
:
public class AccountManager {
private SomeApi api;
@Inject
public AccountManager(SomeApi api) { // errot: SomeApi out of classpath
this.api = api;
}
public void login(String login, String password, Subscriber<Void> subscriber) {
api.login(...) ...
}
}
And then I would use AccountManager
in presentation layer
.
But. Nope. Compile time error.
SomeApi
is in data module
classpath, because domain module
has no gradle dependency on data module
as data module
has android dependency while domain module
hasn't.
There is my solution:
Create LoginApi
interface:
public interface LoginApi {
Observable login(LoginRequest body);
}
Use it in AccountManager
:
public class AccountManager {
private LoginApi api;
@Inject
public AccountManager(LoginApi api) {
this.api = api;
}
...
}
Create implementation of LoginApi
on data-layer
that use SomeApi
:
public class LoginApiImpl implement LoginApi {
private SomeApi api;
@Inject
public LoginApiImpl(SomeApi api) {
this.api = api;
}
Observable login(LoginRequest body) {
return api.login(body);
}
}
And inject it via Dagger 2 in presentation layer
.
Any other ideas?
Activity
Weava commentedon Jun 29, 2016
It seems like your original solution had a
data
module dependency trying to be used in thedomain
module. In this architecture, that is not possible.To keep in-line with what @android10 has created, you may have to create a LoginRepository (or just add a login function to the UserRepository in the existing implementation) like so:
Still in the
domain
layer, have a LoginUseCase that uses the LoginRepository as a component, like so:The
data
layer process might be a bit more involved. This is where you would actually implement your repository pattern for the login case. If you want some sort of login persistence, you will need to implement some form of SharedPreferences or SQLite for storing the data on a successful login, as well as an API to handle the initial request. I won't get too much into that here, as it is quite involved depending on your implementation.In the
presentation
layer, you would inject your LoginRepository from thedomain
layer to use wherever that dependency is needed. It would be advantageous to check if a user is logged in, and have signOut and other important methods in the repository to maintain persistence.This isn't a great implementation by any means, and may even be too complex for your needs. I'm still learning how this architecture works myself, and this is just how I see that a login implementation may work.
Hope this helps.
Let me know if you have any questions.
ghost commentedon Jun 29, 2016
Yep, thanks, but I already came up with the same solution :)
(it described under
There is my solution:
).But Repository mustn't do things like authentification. It must just to provide data. In my case
LoginRepository
is named asLoginApiMediator
.As I think, UseCases is too complex and I came up with Managers. For example, AccountManager does functions of
LoginUseCase
,LogoutUseCase
,ChangePasswordUseCase
etcSome code as bonus:
Dharmendra10 commentedon Jun 30, 2016
@TRY4W Hi, if you can provide some more code or demo to deal with the login API then it will be helpful to me.
android10 commentedon Jul 1, 2016
Retrofit or any other http library is an implementation detail. Basically from my perspective you should try to follow up what is done with other use cases, to keep consistency across the codebase.
I would reuse the UserRepository since it makes sense in this case:
At a data source level you would get the user data from the local storage based on your business rules, otherwise you might try to connect to the api. And of course afterwards go all the way up back to the presentation layer where you would reflect the result at UI level.
android10 commentedon Jul 1, 2016
I would also quote this from @Trikke:
And if you wanna follow up the discussion, here it is:
#151
tigerteamdc2 commentedon Apr 12, 2017
Hi @android10
Suppose that I have SessionManager on the data layer to control user state on the application.
Somewhere on presenter I would like to check whether the user logged in or not.
How can I handle that case?
android10 commentedon Apr 12, 2017
@tigerteamdc2 I would encapsulate everything in a UseCase class and inject it wherever you need.
tigerteamdc2 commentedon Apr 12, 2017
@android10
How could I do using UseCase?
Could I just do something like
Please give some advices on this!