kandi background
Explore Kits

Android-CleanArchitecture | sample app that is part of a series of blog posts | Architecture library

 by   android10 Java Version: Current License: Apache-2.0

 by   android10 Java Version: Current License: Apache-2.0

Download this library from

kandi X-RAY | Android-CleanArchitecture Summary

Android-CleanArchitecture is a Java library typically used in Architecture applications. Android-CleanArchitecture has no vulnerabilities, it has build file available, it has a Permissive License and it has medium support. However Android-CleanArchitecture has 3 bugs. You can download it from GitHub.
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.
Support
Support
Quality
Quality
Security
Security
License
License
Reuse
Reuse

kandi-support Support

  • Android-CleanArchitecture has a medium active ecosystem.
  • It has 14887 star(s) with 3309 fork(s). There are 859 watchers for this library.
  • It had no major release in the last 12 months.
  • There are 127 open issues and 122 have been closed. On average issues are closed in 68 days. There are 17 open pull requests and 0 closed requests.
  • It has a neutral sentiment in the developer community.
  • The latest version of Android-CleanArchitecture is current.
This Library - Support
Best in #Architecture
Average in #Architecture
This Library - Support
Best in #Architecture
Average in #Architecture

quality kandi Quality

  • Android-CleanArchitecture has 3 bugs (2 blocker, 0 critical, 0 major, 1 minor) and 47 code smells.
This Library - Quality
Best in #Architecture
Average in #Architecture
This Library - Quality
Best in #Architecture
Average in #Architecture

securitySecurity

  • Android-CleanArchitecture has no vulnerabilities reported, and its dependent libraries have no vulnerabilities reported.
  • Android-CleanArchitecture code analysis shows 0 unresolved vulnerabilities.
  • There are 3 security hotspots that need review.
This Library - Security
Best in #Architecture
Average in #Architecture
This Library - Security
Best in #Architecture
Average in #Architecture

license License

  • Android-CleanArchitecture is licensed under the Apache-2.0 License. This license is Permissive.
  • Permissive licenses have the least restrictions, and you can use them in most projects.
This Library - License
Best in #Architecture
Average in #Architecture
This Library - License
Best in #Architecture
Average in #Architecture

buildReuse

  • Android-CleanArchitecture releases are not available. You will need to build from source code and install.
  • Build file is available. You can build the component from source.
  • Installation instructions are not available. Examples and code snippets are available.
  • Android-CleanArchitecture saves you 1362 person hours of effort in developing the same functionality from scratch.
  • It has 3051 lines of code, 379 functions and 95 files.
  • It has low code complexity. Code complexity directly impacts maintainability of the code.
This Library - Reuse
Best in #Architecture
Average in #Architecture
This Library - Reuse
Best in #Architecture
Average in #Architecture
Top functions reviewed by kandi - BETA

kandi has reviewed Android-CleanArchitecture and discovered the below as its top functions. This is intended to give you an instant insight into Android-CleanArchitecture implemented functionality, and help decide if they suit your requirements.

  • Download image from url .
  • Gets user entities .
  • Read the file content .
  • Retrieve user entity from cache .
  • Transform users model .
  • Connect to API
  • Creates a message from the given exception .
  • sets the onBindViewHolder on the ListViewHolder
  • Renders the user model .
  • Gets the error message .

Android-CleanArchitecture Key Features

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.

New version available written in Kotlin:

copy iconCopydownload iconDownload
This is a sample app that is part of a blog post I have written about how to architect android application using the Uncle Bob's clean architecture approach.

[Architecting Android…The clean way?](http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/)

[Architecting Android…The evolution](http://fernandocejas.com/2015/07/18/architecting-android-the-evolution/)

[Tasting Dagger 2 on Android](http://fernandocejas.com/2015/04/11/tasting-dagger-2-on-android/)

[Clean Architecture…Dynamic Parameters in Use Cases](http://fernandocejas.com/2016/12/24/clean-architecture-dynamic-parameters-in-use-cases/)

[Demo video of this sample](http://youtu.be/XSjV4sG3ni0)

Clean architecture

Local Development

copy iconCopydownload iconDownload
Refer to the issues section: https://github.com/android10/Android-CleanArchitecture/issues


Code style
-----------

Here you can download and install the java codestyle.
https://github.com/android10/java-code-styles


License
--------

    Copyright 2018 Fernando Cejas

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.


![http://www.fernandocejas.com](https://github.com/android10/Sample-Data/blob/master/android10/android10_logo_big.png)

[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Android--CleanArchitecture-brightgreen.svg?style=flat)](https://android-arsenal.com/details/3/909)

<a href="https://www.buymeacoffee.com/android10" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: auto !important;width: auto !important;" ></a>

Making synchronous calls to Cloud Firestore when running off the main thread

copy iconCopydownload iconDownload
suspend fun movieList(): List<MovieEntity>
launch(UI) {
    try {
        val list = movieList()
        ...
    } catch (e: FireException) {
        // handle
    }
}
-----------------------
suspend fun movieList(): List<MovieEntity>
launch(UI) {
    try {
        val list = movieList()
        ...
    } catch (e: FireException) {
        // handle
    }
}
-----------------------
private fun movieListResponse(): Call.Response<List<MovieEntity>> {
        return try {
            val taskResult = Tasks.await(FirebaseFirestore.getInstance().
                    collection(DataConfig.databasePath + MOVIES_PATH).get(), 2, TimeUnit.SECONDS)
            Call.Response(true, taskResult.mapTo(ArrayList()) { MovieEntity.fromSnapshot(it) }, null)
        } catch (e: ExecutionException) {
            Call.Response(false, null, Failure.ServerError())
        } catch (e: InterruptedException) {
            Call.Response(false, null, Failure.InterruptedError())
        } catch (e: TimeoutException) {
            Call.Response(false, null, Failure.TimeoutError())
        }
    }

disjoint union in Kotlin to get access in Java

copy iconCopydownload iconDownload
@Override public Unit invoke(
    Either<? extends Failure, ? extends TokenInfo> either) {
        either.either(f -> ..., tokenInfo -> ...);
        return Unit.INSTANCE;
}

Getting NullPointException when using Dagger2 and setRetainInstance(true);

copy iconCopydownload iconDownload
public abstract class BaseFragment extends Fragment {

    private boolean mIsInjected = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);

        try {
            mIsInjected = onInjectView();
        } catch (IllegalStateException e) {
            Log.e(e.getClass().getSimpleName(), e.getMessage());
            mIsInjected = false;
        }
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (mIsInjected) onViewInjected(savedInstanceState);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (!mIsInjected) {
            mIsInjected = onInjectView();
            if (mIsInjected) onViewInjected(savedInstanceState);
        }
    }

    @SuppressWarnings("unchecked")
    protected <C> C getComponent(Class<C> componentType) throws IllegalStateException {
        C component = componentType.cast(((HasComponent<C>) getActivity()).getComponent());
        if (component == null) {
            throw new IllegalStateException(componentType.getSimpleName() + " has not been initialized yet.");
        }
        return component;
    }


    protected boolean onInjectView() throws IllegalStateException {
        // Return false by default.
        return false;
    }

    @CallSuper
    protected void onViewInjected(Bundle savedInstanceState) {
        // Intentionally left empty.
    }
 }
public class SampleFragment extends BaseFragment implements SampleView {

    @Inject
    SamplePresenter mSamplePresenter;

    @Override
    protected boolean onInjectView() throws IllegalStateException {
        getComponent(SampleComponent.class).inject(this);
        return true;
    }

    @Override
    protected void onViewInjected(Bundle savedInstanceState) {
        super.onViewInjected(savedInstanceState);
        this.mSamplePresenter.setView(this);
    }
}
-----------------------
public abstract class BaseFragment extends Fragment {

    private boolean mIsInjected = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);

        try {
            mIsInjected = onInjectView();
        } catch (IllegalStateException e) {
            Log.e(e.getClass().getSimpleName(), e.getMessage());
            mIsInjected = false;
        }
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (mIsInjected) onViewInjected(savedInstanceState);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (!mIsInjected) {
            mIsInjected = onInjectView();
            if (mIsInjected) onViewInjected(savedInstanceState);
        }
    }

    @SuppressWarnings("unchecked")
    protected <C> C getComponent(Class<C> componentType) throws IllegalStateException {
        C component = componentType.cast(((HasComponent<C>) getActivity()).getComponent());
        if (component == null) {
            throw new IllegalStateException(componentType.getSimpleName() + " has not been initialized yet.");
        }
        return component;
    }


    protected boolean onInjectView() throws IllegalStateException {
        // Return false by default.
        return false;
    }

    @CallSuper
    protected void onViewInjected(Bundle savedInstanceState) {
        // Intentionally left empty.
    }
 }
public class SampleFragment extends BaseFragment implements SampleView {

    @Inject
    SamplePresenter mSamplePresenter;

    @Override
    protected boolean onInjectView() throws IllegalStateException {
        getComponent(SampleComponent.class).inject(this);
        return true;
    }

    @Override
    protected void onViewInjected(Bundle savedInstanceState) {
        super.onViewInjected(savedInstanceState);
        this.mSamplePresenter.setView(this);
    }
}

How to mock final class with Mockito 2 on Java Module in Android project?

copy iconCopydownload iconDownload
compile "org.mockito:mockito-core:$mockito_version"
compile "org.mockito:mockito-inline:$mockito_version"
-----------------------
compile "org.mockito:mockito-core:$mockito_version"
compile "org.mockito:mockito-inline:$mockito_version"

Publish to specific Observer using PublishSubject

copy iconCopydownload iconDownload
public class DataStore {

    private PublishSubject<DataItem> dataItemPublishSubject = PublishSubject.create();

    public Flowable<DataItem> getAllObservable() {
        return dataItemPublishSubject.toFlowable(BackpressureStrategy.BUFFER);
    }

    public Flowable<DataItem> getPopularObservable() {
        return dataItemPublishSubject.toFlowable(BackpressureStrategy.BUFFER)
                .filter(new Predicate<DataItem>() {
                    @Override
                    public boolean test(DataItem dataItem) throws Exception {
                        return dataItem.popular;
                    }
                });
    }

    public static class DataItem {
        public final boolean popular;

        public DataItem(boolean popular) {
            this.popular = popular;
        }
    }
}
    dataStore.getAllObservable()
            .doOnNext(new Consumer<DataStore.DataItem>() {
                @Override
                public void accept(DataStore.DataItem dataItem) throws Exception {
                    pagerAdapter.addDataAll(dataItem);      
                }
            })
            .filter(new Predicate<DataStore.DataItem>() {
                @Override
                public boolean test(DataStore.DataItem dataItem) throws Exception {
                    return dataItem.popular;
                }
            })
            .doOnNext(new Consumer<DataStore.DataItem>() {
                @Override
                public void accept(DataStore.DataItem dataItem) throws Exception {
                    pagerAdapter.addDataPopular(dataItem);
                }
            })
            .subscribe();
-----------------------
public class DataStore {

    private PublishSubject<DataItem> dataItemPublishSubject = PublishSubject.create();

    public Flowable<DataItem> getAllObservable() {
        return dataItemPublishSubject.toFlowable(BackpressureStrategy.BUFFER);
    }

    public Flowable<DataItem> getPopularObservable() {
        return dataItemPublishSubject.toFlowable(BackpressureStrategy.BUFFER)
                .filter(new Predicate<DataItem>() {
                    @Override
                    public boolean test(DataItem dataItem) throws Exception {
                        return dataItem.popular;
                    }
                });
    }

    public static class DataItem {
        public final boolean popular;

        public DataItem(boolean popular) {
            this.popular = popular;
        }
    }
}
    dataStore.getAllObservable()
            .doOnNext(new Consumer<DataStore.DataItem>() {
                @Override
                public void accept(DataStore.DataItem dataItem) throws Exception {
                    pagerAdapter.addDataAll(dataItem);      
                }
            })
            .filter(new Predicate<DataStore.DataItem>() {
                @Override
                public boolean test(DataStore.DataItem dataItem) throws Exception {
                    return dataItem.popular;
                }
            })
            .doOnNext(new Consumer<DataStore.DataItem>() {
                @Override
                public void accept(DataStore.DataItem dataItem) throws Exception {
                    pagerAdapter.addDataPopular(dataItem);
                }
            })
            .subscribe();

RxJava polling + manual refresh

copy iconCopydownload iconDownload
    // Specific example of a user manually requesting
    val request = Observable.create<String> { emitter ->
        refresh.setOnClickListener {
            emitter.onNext("Click Request")
        }
    }
            .observeOn(Schedulers.io())
            .flatMap {
                userRepository.users()
            }

    // Refresh based off of your original work, could use something like interval as well
    val interval = userRepository.users()
            .subscribeOn(Schedulers.io())
            .repeatWhen { objectObservable ->
                objectObservable.delay(1, TimeUnit.MINUTES)
            }

    // Combine them so that both emissions are received you can even add on another source
    Observable.merge(request,interval)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                contents.text = it.toString()
            }, {
                contents.text = it.toString()
            },{
                println(contents.text)
            })
-----------------------
@Test
public void intervalObservableAndImmediateReaction() throws InterruptedException {
    Observable<String> obs = Observable.interval(1, TimeUnit.SECONDS)
                .cast(Object.class)                                          
                .mergeWith(
                          Observable.just("mockedUserClick")
                                    .delay(500, TimeUnit.MILLISECONDS))
                .flatMap(
                         timeOrClick -> Observable.just("Generated upon subscription")
                         );

    obs.subscribe(System.out::println);
    Thread.currentThread().sleep(3000); //to see the prints before ending the test
}
Observable.interval(1, TimeUnit.MINUTES)
            .mergeWith(RxView.clicks(buttonView))
            .flatMap(timeOrClick -> this.userRepository.users());
RxView.touches(yourViewVariable)
      .flatMatp(motionEvent -> this.userRepository.users())
      .subscribe(theObserver);
-----------------------
@Test
public void intervalObservableAndImmediateReaction() throws InterruptedException {
    Observable<String> obs = Observable.interval(1, TimeUnit.SECONDS)
                .cast(Object.class)                                          
                .mergeWith(
                          Observable.just("mockedUserClick")
                                    .delay(500, TimeUnit.MILLISECONDS))
                .flatMap(
                         timeOrClick -> Observable.just("Generated upon subscription")
                         );

    obs.subscribe(System.out::println);
    Thread.currentThread().sleep(3000); //to see the prints before ending the test
}
Observable.interval(1, TimeUnit.MINUTES)
            .mergeWith(RxView.clicks(buttonView))
            .flatMap(timeOrClick -> this.userRepository.users());
RxView.touches(yourViewVariable)
      .flatMatp(motionEvent -> this.userRepository.users())
      .subscribe(theObserver);
-----------------------
@Test
public void intervalObservableAndImmediateReaction() throws InterruptedException {
    Observable<String> obs = Observable.interval(1, TimeUnit.SECONDS)
                .cast(Object.class)                                          
                .mergeWith(
                          Observable.just("mockedUserClick")
                                    .delay(500, TimeUnit.MILLISECONDS))
                .flatMap(
                         timeOrClick -> Observable.just("Generated upon subscription")
                         );

    obs.subscribe(System.out::println);
    Thread.currentThread().sleep(3000); //to see the prints before ending the test
}
Observable.interval(1, TimeUnit.MINUTES)
            .mergeWith(RxView.clicks(buttonView))
            .flatMap(timeOrClick -> this.userRepository.users());
RxView.touches(yourViewVariable)
      .flatMatp(motionEvent -> this.userRepository.users())
      .subscribe(theObserver);

Kotlin+Mockito2: ClassNotFoundException for presenter tests

copy iconCopydownload iconDownload
sourceSets {
    main.java.srcDirs += 'src/main/java'
    main.java.srcDirs += [file("$buildDir/generated/source/kapt/main")]
    main.java.srcDirs += '../data/src/main/java'
    main.java.srcDirs += '../entities/src/main/java'
    main.java.srcDirs += '../domain/src/main/java'
  }

execute multiple Subscribers rxjava

copy iconCopydownload iconDownload
@Test
public void name() throws Exception {
    Observable<SearchResponseDomain> departureTrip = getCompanies();
    Observable<SearchResponseDomain> returnTrip = getCompanies();

    // Subs. to both observables. If one finishes -> whole stream closes
    Observable<List<SearchResponseDomain>> zip = Observable.zip(departureTrip, returnTrip, (d, r) -> {
        return Arrays.asList(d, r);
    });

    // Subscribe
    zip.observeOn(AndroidSchedulers.mainThread())
            .subscribe(searchResponseDomain -> {
                // show stuff in UI
            });

}

// TODO: add params to getCompanies...
private Observable<SearchResponseDomain> getCompanies() {
    return Observable.just(new SearchResponseDomain());
}

class SearchResponseDomain {

}

How can I trigger a model to give new data when a save occurs

copy iconCopydownload iconDownload
return bookRepository.getLibrary()
        .repeatWhen(e -> eventBus.toObservable()
                .filter(event -> event.equals(LIBRARY_CHANGED)));
public class EventBus {

    private final PublishSubject<Object> _bus = PublishSubject.create();

    public void post(Object event) {
        _bus.onNext(event);
    }

    public Observable<Object> toObservable() {
        return _bus;
    }
}
repository.searchLibrary(params.searchTerm)
    .doOnComplete(() -> eventBus.post(LIBRARY_CHANGED));
-----------------------
return bookRepository.getLibrary()
        .repeatWhen(e -> eventBus.toObservable()
                .filter(event -> event.equals(LIBRARY_CHANGED)));
public class EventBus {

    private final PublishSubject<Object> _bus = PublishSubject.create();

    public void post(Object event) {
        _bus.onNext(event);
    }

    public Observable<Object> toObservable() {
        return _bus;
    }
}
repository.searchLibrary(params.searchTerm)
    .doOnComplete(() -> eventBus.post(LIBRARY_CHANGED));
-----------------------
return bookRepository.getLibrary()
        .repeatWhen(e -> eventBus.toObservable()
                .filter(event -> event.equals(LIBRARY_CHANGED)));
public class EventBus {

    private final PublishSubject<Object> _bus = PublishSubject.create();

    public void post(Object event) {
        _bus.onNext(event);
    }

    public Observable<Object> toObservable() {
        return _bus;
    }
}
repository.searchLibrary(params.searchTerm)
    .doOnComplete(() -> eventBus.post(LIBRARY_CHANGED));

Community Discussions

Trending Discussions on Android-CleanArchitecture
  • In clean MVP, who should handle combining interactors?
  • Making synchronous calls to Cloud Firestore when running off the main thread
  • disjoint union in Kotlin to get access in Java
  • Clean architecture: Use CompositeDisposable in domain or presentation/app
  • How to setup a project for Clean architecture in gradle?
  • Getting NullPointException when using Dagger2 and setRetainInstance(true);
  • How to mock final class with Mockito 2 on Java Module in Android project?
  • Android app clean architecture: Should data layer have its own model classes?
  • Android library module does not compile when using classes from pure Kotlin module
  • Publish to specific Observer using PublishSubject
Trending Discussions on Android-CleanArchitecture

QUESTION

In clean MVP, who should handle combining interactors?

Asked 2019-Apr-12 at 16:21

I've seen good examples of MVP architecture (here and here). Both present only simple interactors, but I wonder how to deal with more complex use case, consisting of steps, which are repeated in other use cases.

For example, my API requires token to authenticate any call. I've created an interactor to get that token (GetToken). I want to get user's last login date (GetLastLoginDate) and then fetch a list of changes that occured between that date and now (GetVersionChanges).

Where those interactor should be chained? I want to keep them separate, because some of them are reused in other parts of the code. I've came up with two solutions.

  1. Presenter should chain all interactors. This solution works as long the use case is not complex and doesn't have many preconditions. It seems to me it's not the right place, because it burdens presenter with another responsibility.

  2. Interactor can use many repositories (no clean architecture rules are broken then). Why not use TokenRepository in other interactors? Because getting token is much more complex than just reaching to repository. Repeating the steps in other interactor does not reuse already existing code.

Both solutions have their flaws and are against basic principles (DRY, single responsibility principle).

ANSWER

Answered 2019-Apr-12 at 16:21

If I were you I would just put the logic of getting a token in a separate interactor (maybe named getTokenInteractor) and call that interactor from your others interactor who may need it. That way, it would be in an interactor that you chose either to use a token (and call or not your getTokenInteractor) and also in an interactor that you retrieve it and deal with errors. I would do the same for your "getVersionChanges" use case and let an interactor chain the calls.

Let's imagine you have a presenter who needs to display the version changes. He will call a first interactor (GetVersionChangesInteractor) who will first check if he has a token (by calling getTokenInteractor), then call GetLastLoginDateRepository for retrieving the date, and call GetVersionChangesRepository with that date and finally give the result to your presenter.

That way, your business logic can stay 100% in your interactor and your presenter can focus on how he will display that on screen.

By the way, if your API needs a token for every call you should move it in an Interceptor so you do not have to deal with it at every call.

Source https://stackoverflow.com/questions/47868684

Community Discussions, Code Snippets contain sources that include Stack Exchange Network

Vulnerabilities

No vulnerabilities reported

Install Android-CleanArchitecture

You can download it from GitHub.
You can use Android-CleanArchitecture like any standard Java library. Please include the the jar files in your classpath. You can also use any IDE and you can run and debug the Android-CleanArchitecture component as you would do with any other Java program. Best practice is to use a build tool that supports dependency management such as Maven or Gradle. For Maven installation, please refer maven.apache.org. For Gradle installation, please refer gradle.org .

Support

For any new features, suggestions and bugs create an issue on GitHub. If you have any questions check and ask questions on community page Stack Overflow .

DOWNLOAD this Library from

Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases

Save this library and start creating your kit

Explore Related Topics

Share this Page

share link
Reuse Pre-built Kits with Android-CleanArchitecture
Compare Architecture Libraries with Permissive License
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases

Save this library and start creating your kit

  • © 2022 Open Weaver Inc.