Coder Social home page Coder Social logo

android10 / android-cleanarchitecture Goto Github PK

View Code? Open in Web Editor NEW
15.5K 15.5K 3.3K 5.07 MB

This is a sample app that is part of a series of blog posts I have written about how to architect an android application using Uncle Bob's clean architecture approach.

License: Apache License 2.0

Java 100.00%
android android-application android-architecture android-cleanarchitecture android-development architectural java

android-cleanarchitecture's Introduction

Fernando-Cejas

How to reach me...

GitHub Stats Fernando's GitHub Stats
Most Used Languages Fernando's GitHub Top Languages

android-cleanarchitecture's People

Contributors

android10 avatar dmitriyzaitsev avatar elevenfive avatar lalongooo avatar rashiq avatar rynkowsg avatar sebastienrouif avatar xingmingli avatar yukimatsumura avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

android-cleanarchitecture's Issues

Considering activity lifecycle

Hi,
first of all thank you for your work.
One think i didn't understand is how to deal with the lifecycle of the activities related to the jobexecutor as the jobs are running in a threadpool and i need the possibility to cancel a job (while navigating through activities).
Can you give an example how you would integrate for example Loaders (or is using loaders not a good approach in this architecture) or RxJava?
Another question is, when and how to cleanup references (like callback in interactor, when presenter is no more interested in interactor results).

UserComponent void inject(UserListActivity userListActivity);

If I added "void inject(UserListActivity userListActivity) " method to UserComponent,It reports an error "Error:(20, 78) 错误: 找不到符号
符号: 类 DaggerApplicationComponent
位置: 程序包 com.fernandocejas.android10.sample.presentation.internal.di.components
/Users/liuzhuang/AndroidStudioProjects/Android-CleanArchitecture10/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/activity/UserListActivity.java
Error:(13, 78) 错误: 找不到符号
符号: 类 DaggerUserComponent
位置: 程序包 com.fernandocejas.android10.sample.presentation.internal.di.components
/Users/liuzhuang/AndroidStudioProjects/Android-CleanArchitecture10/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/view/activity/UserDetailsActivity.java
Error:(13, 78) 错误: 找不到符号
符号: 类 DaggerUserComponent
位置: 程序包 com.fernandocejas.android10.sample.presentation.internal.di.components
/Users/liuzhuang/AndroidStudioProjects/Android-CleanArchitecture10/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/internal/di/components/UserComponent.java
Error:(35, 8) 错误: com.fernandocejas.android10.sample.presentation.navigation.Navigator cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method. This type supports members injection but cannot be implicitly provided.
com.fernandocejas.android10.sample.presentation.view.activity.BaseActivity.navigator
[injected field of type: com.fernandocejas.android10.sample.presentation.navigation.Navigator navigator]
4 个错误
Error:Execution failed for task ':presentation:compileDebugJava'.

Compilation failed; see the compiler error output for details."

Explanation of @PerActivity

This is not really an issue, as much as a question: How is the @PerActivity scope enforced?

I can never seem to find how exactly scopes work in Dagger 2. Could you may be eleborate more on that? (or provide a link where it is explained?)

The project isn't working in Android Studio 1.2 RC 2

I tried to open the project with Android Studio (File > Open... > root build.gradle). No erros appears, expect that if I try to open any source file, the editor shows compilation errors about not finding the classes imported. It seems that Android Studio isn't understanding the dependencies of the modules.

Problem with retry api calling.

Hello guys,
When I open the application and have no connection , the window " Retry " appears, if i press the button, the application blocked and I don't get any response from the server.

I have been researching and I think that when you make the call (this.loadUsers()), if you have no connection, RxJava send you an onError() message, and you get the window "Retry". Then if you try to make the call again, RxJava don't create any new thread and it blocks you on "loop" method.

Maybe we should use Retrofit here?

I wonder if it happened to someone else , thank you.

Pd: Sorry for my bad english.

Database vs. Rest Api

I've following use case:
I want to mark an user as default (only one user can be the default user).

If I'm using a database i need a transaction:

  1. reset default flag to false on "old" user
  2. set default flag to true on "new" user

Where should I create the transaction and the two update operations? In the datastore? In the repository? In a domain layer class (UserManager)?

What if I change to a REST-Api? In that case I don't need that transaction anymore (because the API provides an method which includes the two steps above already) – how can I achieve this by only changing the dependencies?

Could you please give me an advise?

Doubt about source code quality

First of all sorry for my regular english, it's not my main language.

I found your article interesting and helpful, the best practice in terms of source code organization in my opinion.

What is your opinion about PMD, CheckStyle and FindBugs in Android projects?

I've found an article that explain how to put these tools to work with gradle build.
Here: http://vincentbrison.com/2014/07/19/how-to-improve-quality-and-syntax-of-your-android-code
Source: https://github.com/vincentbrison/vb-android-app-quality

I put it to work with your source code structure, and it works with android based projects, but not with the java project.

Maybe you can help me with that. Could you?

Thanks.

UseCases

How do you handle more than one UseCase per Activity? For example if you have the possibility to delete, rate a user, etc. how do you handle that? Is it allowed to assign more than one use case to the presenter? Or do you have only one use case which handles all needed operation for you?

Btw. very nice and interesting post.

How to deal with transactions in domain layer

I have a question about handling transactions between data and domain layer.
Think about a usecase where two entities should be persisted into a local database in one transaction.
Should the domain layer know something about "transactions" when calling into the data layer and what about "nested transaction"? Who is responsible to decide whether two or more operations should handled atomic as the domain layer doesn't know something about where and how the data is persisted.
Another point is also how to handle if there is a foreign key relationship between entities.

Thank you for any advice.

JUnit version 3.8 or later expected

Hi,
I am trying to learn from your code so i have started from domain module. I have copied build.gradle content of both project and domain module also copied the buildsystem folder content from your project to mine. when i run a test case i got "JUnit version 3.8 or later expected"

I have cloned your repository and it works fine.. i am sure my project structure is similar to yours ..
I really don't know what is the problem in my project and how to solve it

Application Logic

First off, this is not a bug report, but more an architectural inquiry.

While your project and blog give out perfectly suitable outlines to make a data-centric app, i'm wondering about where you'd put application specific logic, for instance an android specific location provider. I'd think that a user presses a button "get current location", which through the presentation layer, fires of a use case in the domain logic. Which in turn would have a reference to that location provider, gather data and then return a formatted response back up to the user.

Should that location provider also be in the data layer, since it's about location data? Or would it be correct to assume that, since the location provider is specific to the platform and application, you'd want to create another sub-project application and reference it in the domain layer. The application layer would then hold things like the location provider, notification manager, logging framework and so on.

I'd like to hear your input in this matter.

Best practice to pass dynamic parameters to an UseCase?

As in the example, usecase's parameters are set via UserModule:

@Module
public class UserModule {
  private int userId = -1;
  public UserModule() {}

  public UserModule(int userId) {
    this.userId = userId;
  }

  @Provides @PerActivity @Named("userDetails") UseCase provideGetUserDetailsUseCase(
      UserRepository userRepository, ThreadExecutor threadExecutor,
      PostExecutionThread postExecutionThread) {
    return new GetUserDetailsUseCase(userId, userRepository, threadExecutor, postExecutionThread);
  }
}

But there are some cases when buildUseCaseObservable depends on some dynamic parameters. I tried to create an interface to provide these parameters and let the view (in MVP) implement it and pass them to UserModule. With this approach if the view is a Fragment then I have to re-create UserModule again in the Fragment.

public interface UserIdProvider {
  int getUserId();
}

Any suggestion, recommendation?

Can I use this architecture in real project?

This is not an issue.
It's really a clearly defined architecture. A lot of technologies are introduced into the architecture, I 've never used them before, Dagger, RxAndroid, Butternife, etc.
But I am little confused by the fine defined UseCases, for example , GetUserList, GetUserDetails for user usecases. If I want to do user search, I must define SearchUser usecase, I want to do CRUD for many many Objects, I need to write hands of usecases separately.
And, I'm not sure how to pass parameters to the usecases. For example, GetUserDetails, pass the userId by constructor in UserModule. How can I pass a search critera to SearchUser UseCase? A Map? Or a Model? Is there another way instead of constructor?

Thank you very much for any suggestion.

NullPointerException in mock provided class

Hi,
I am trying to provide a mock implementation of a Retrofit RestAdapter for my unit test. However, restAdapter.build(); keeps throwing this exception

Cannot return null from a non-@nullable @provides method

What should I do to resolve this?

Thank you,
Igor

Why RxJava?

I'm new to Android development and have been reading your blog post about clean architecture. From the commit history (and that I don't find any mention of it in your post), I see that you introduced RxJava much later in the project. I wanted to understand what architectural problem did RxJava solve for you (Like Dagger did for object creation)?

UserListPresenter#onUserClicked naming

Hi, very interesting post.

I have a method naming question/issue.

In the UserListPresenter, you have defined a method onUserClicked(UserModel userModel). I'm not sure if this is a correct name. The idea is that the View can change but the presenter remains the same, but the concept of UserClicked is something more of the view. Maybe the view changes and the user is displayed in a double click.

In my opinion this method should be called something like viewUserDetail(UserModel userModel).

Thanks,

AutoLoadImageView breaking the rules?

Hi guys,

at first, thanks for the great project. I enjoyed to read about this topic and fiddle around with your project.
So I think I get the main concept, but one think bothers me: the AutoLoadImageView.

It seems to me, that these view component breaks with the basic concept of the clean architecture.
Here we have model stuff like the cache and network access, as well as a lot of business logic like checking the internet connection and changing the loading logic. What's the reason for that? Thanks for your help in advance.

Thead never end on reexecute

When you doesn't have network and you click on the retry button, the thread never end. O think it's come from the UseCase.execute because it's recreate the observable.

Parametrize UseCases in the domain layer with some "output" type

Hi all! Thank you for the interesting project and discussions! I have two questions regrading the "output" type for the use cases in the domain layer. Under the "output" type i mean the type, which will be passed to the presentation layer from the domain layer.

  1. In this example project the "User" type(from domain layer) is used as an output type (in GetUserDetails and GetUsetrList UseCases) and will be passed to the presentation layer. Can i pass some another type to the presentation layer? Suppose, some type UserMod, those fields are somehow composed from the User fields. Or this is not correct understanding of the architecture?
  2. What we will break, if we parametrize the UseCase abstract class like
public abstract class UseCase<T> {

protected abstract Observable<T> buildUseCaseObservable();

public void execute(Subscriber<T> useCaseSubscriber) { ... }
} 

so, a concrete use case will look like:

public class GetUserDetails extends UseCase<User> {

  //constructor here

  @Override protected Observable<User> buildUseCaseObservable() { ... }
} 

Thus a subscriber for the use case will be bounded with this "output" type too. Does this make any sense?
Thanks in advance!

How to get an Object from api instead of array

Hi,
Thanks for this great tutorial. really you help me a lot to learn news ideas specially RxJava and Dagger 2.
I am new to Android and Java but i think, it would be great if you use Retrofit for api calss also Parcelables.

in my case, i have api response comes in objects not in array. so, what changes should i do to receive objects?

Thanks a lot

Lifecycle Questions

Hello,

could it be dangerous if Presenters and Interactors are defined as a Singelton? For example if I store the received data from the network in an instance variable of the Presenter, so that variable remains in memory for the hole application lifetime?

What happens if a network task needs for some some reasons more time as usually? Remains the view (Activity) of the Presenter in memory? Is there an advice when to clear it out?

Dependency rule is broken

As you say in your post, "source code dependencies can only point inwards and nothing in an inner circle can know anything at all about something in an outer circle.". Then UserEntityDataMapper shouldn't be in data module, because it knows about User.class of domain module that is in an outer circle. Is there any reason for creating it there instead of in domain module or is it just a mistake?

Anyway, great example of how to build a clean architecture!

How to test your views?

I didn't see any unit tests for the Fragments. How do you inject a mockPresenter into your fragment to test it?

UserDataRepository breaks dependecy rules

Hi,

didn't UserDataRepository breaks dependency rules? Class is from data layer but implements userrepository interface which is from domain layer.

thanks
rohliq

New http request on conf changes

I like how you architectured your application but, in a real android app. you would't want to waste resources and make new network request every time the user does something as simple as rotating their phone.

Why not skip the domain layer?

Hi,
Kudos for the great blog post and this repository! 👍

The thing that bugs me is that you referred to a domain layer.
In my opinion (in most of the cases) the domain layer should only exist on the server side, referring to a domain layer in the client side is misleading.

Skipping the implementation of a domain layer in the client altogether could actually save ton of work, instead of publishing updates with the "domain" object as payload and coupling it to all of the subscribers you could publish an update with a DTO as the payload to the relevant presenters.

The interactor layer is awesome, it resembles Flux architecture events and I agree is really useful, but again you could keep it and just skip the "domain" entities.

What are the tradeoffs in your opinion?

Best regards,
Erik.

Data Layer with Android Dependencies

I have only skimmed through the source code, but I noticed that the UserDataStoreFactory and the RestApiImpl have a dependency on Android libraries. This appears to break the rule for the Clean Architecture Dependency Rule: "source code dependencies can only point inwards and nothing in an inner circle can know anything at all about something in an outer circle."

Is the Android Context used for the UserDataStoreFactory and could it be removed?

Is it possible to check connectivity from RestApi without dependency on Android libraries?

I am trying to find an architecture that I can write my core library that would interface with both mobile and web apps. I like the concepts of the Clean Architecture for this.

Threading with Pool and cgroups

Hi Fernando,

I really like the architecture.
early P.S - There is no way to register to leave comment on your website so this is why I am writing here.

It would be cool to apply threading priority (see link) to the current architecture
http://www.androiddesignpatterns.com/2014/01/thread-scheduling-in-android.html

Process class which sets priority is an android class.
One possible solution is to make domain layer an android module but would be cool to avoid this.
Is there a way to set this to the thread pool somehow?

As for result handling, I would suggest using callbacks like this
done(Result result, Exception e)
instead of two methods
onResult(), onError()
which quickly adds up to verbose code.

let me know what you think

DaggerCppComponent initialize is empty

Hi,I user dagger2 in my project . I create a component called CppComponent and an activity called LoginActivity. Dagger2 build an implementation class called DaggerCppComponent,but the class DaggerCppComponent's method initialize is empty. It did not init the LoginActivity_MembersInjector class which is built by Dagger2.

UseCase problem?

Hi, I'm recently working on my android project code refactoring and I find your project.

I'm confused about using UseCase class which will be @Inject in Presentation Layer to get the data in Data Layer.
Will this be more convenient if we just @Inject the UserRepository in Presentation Layer directly, since UseCase(GetUserDetails) is just some kind of wrapping of UserRepository from my point of view.

Like this:

class UserDetailsPresenter{
    private UserRepository userRepository;
    ...
    @Inject
    public UserDetailsPresenter(UserRepository userRepository){
        ...
    }    
    ...
    //get the user detail
    userRepository.user(this.userId).subscribeOn(...).observeOn(...).subscribe((data)->{});
    ....
}

Push events in the data layer to the presentation layer

What about update events in the data layer and how to notify about them the presentation layer? Let's suppose, that some third party service has updated some user data in the data base.

Is event bus approach good for that?
For example, we will define some event class in the domain layer: UserUpdatedEvent. Some presenter in the presentation can subscribe/unsubscribe for this event on the event bus. Data layer can post the UserUpdatedEvent on event bus ...

Chain use cases.

Hi guys,
Thanks for your project, it is great).
I was wondering whether I can execute one use case with the results of the previous without callback hell?

Packages by feature

@android10 I read the article which you have written for this example and I read that you prefer and you suggest to use package by feature. We decided to follow this architecture which you described (with a few changes), but as a DevTeam we want to follow this kind of logic (for ownership) that's why I want to ask you how it can be this kind of approach for package by feature.

Let's say I am in Domain layer and I have the following features authentication, search. I will have the followings:

com.test.domain.authentication
├─ exception
├─ executor
├─ interactor
├─ repository

com.test.domain.search
├─ exception
├─ executor
├─ interactor
├─ repository

Right? The same logic for each layer (data, presentation) in order to be packaged by feature.

Navigator question

Hi,
I see that you use navigator direct in activity, not trough presenter, this is because activity haven't presenter or because navigator also looks like a ~ specific presenter?

Thanks

A question regarding navigation

Hi, thank you for a fantastic example app.

I notice that you are using a custom Navigator class for launching activities (with arguments and so forth). I would like to know how you would integrate Navigator class into startActivityForResult and onActivityResult use case.

I could think of a few options for decoupling these "View" classes. i.e. ActivityA starting ActivityB by creating Intent with direct reference to Activity B

  1. Ditching this whole "ForResult" idea altogether.
  2. Introducing "callbacks" which would be called in DestinationActivity before finishing.
  3. Navigator supplying navigateToSomeActivity(... int requestCode); and calling Activity/Fragment handles the results via plain old onActivityResult

I am leaning more towards option 3, but I would love to know more of your opinions (and possible implementations in this example in the future maybe?).

Thanks a lot.

Where Content Provider and Service would fit?

This is not an issue, just an architectural question...

Let's say that our application has a SQLite database, a Content Provider that exposes this data and an IntentService that is responsible for syncing data by calling the REST service and updating the database.

Where these two components should be placed?

I think The ContentProvider would easily be placed in the data module.
An additional Repository implementation in the data module would query the content provider and transform the cursor data into entity objects in order to be consumed by the Use Cases. For the UseCase there's no difference. It will still talk to the interface and it will get back the data it wants. Of course, the proper concrete implementation would be injected via dagger.

The Service could also be placed in the data module.

A new interface could be introduced in the domain, i.e. SyncRepository which will be used by the Use Case. The actual implementation of it (in the data module) will start the service with an Intent.

What do you think?

Accessing methods of Android LocationManager, AlarmManger,...

How do you access for example methods of the LocationManager or the AlarmManager? And where should they be located in your described architecture? Domain-, Data- or Presentation-Layer? In my opinion it should be placed in the Datalayer and accessed through an interface.

How would I apply usecases to some kind of background service?

I'm trying to use this architecture in my project. In my case, I have a timer that the user will be able to start, pause and stop. We could also think of an example of a music player. In this case, what should be the usecases?

StartTimerUsecase, StopTimerUsecase and so on? All those usecases would point to the same service, right? And, it would need the service to be an actual Android Service, so it could run independent of the UI. How could I manage it?

Thanks in advance.

A branch where dagger is not implemented

Hi, i was wondering if you could make a branch from the time before you use injection, I just read the "Architecting Android…The clean way?" and it would be great to see the code at that time, Great article by the way.

Json Serializer

So, whats the deal with the JsonSerializer class? Just asking.

I think you can serialize the UserEntity with the UserEntityJsonMapper, just adding the serializer methods.

I've found another way do use the gson, without use the Type.
Source: http://stackoverflow.com/a/17300003/1703546

I've changed the class methods, and ran the tests and is working fine.

Entity:

UserEntity userEntity = this.gson.fromJson(userJsonResponse, UserEntity.class);

Entity Collection:

final UserEntity[] userEntityArray = this.gson.fromJson(userListJsonResponse, UserEntity[].class);
userEntityCollection = new ArrayList<>(Arrays.asList(userEntityArray));

Code styles

Could you add to project the code styles you used in order to create a pull request with some very small but good changes? ^^

Thx mate.

BTW, very good job :-)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.