Support
Quality
Security
License
Reuse
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.
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:
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
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.

[](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
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
@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);
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?
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
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
// 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
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
@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
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));
QUESTION
In clean MVP, who should handle combining interactors?
Asked 2019-Apr-12 at 16:21I'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.
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.
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:21If 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.
Community Discussions, Code Snippets contain sources that include Stack Exchange Network
No vulnerabilities reported
Save this library and start creating your kit
Explore Related Topics
Save this library and start creating your kit