Skip to content

Commit

Permalink
Updated conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
sockeqwe committed Nov 28, 2017
2 parents 6a54542 + de11781 commit fcfefec
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
*
* <p>
* Mosby assumes that all interaction (i.e. updating the View) between Presenter and View is
* executed on android's main UI thread.
* executed on Android's main UI thread.
* </p>
*
* @author Hannes Dorfmann
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,149 +2,157 @@

import android.support.annotation.MainThread;
import android.support.annotation.NonNull;

import java.lang.ref.WeakReference;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
* This Presenter implementation queues ({@link ViewAction} to interact with the view layer if no
* view is attached.
* view is attached by using {@link #onceViewAttached(ViewAction)}.
* Once a view is (re)attached, the queued {@link ViewAction} will be executed one after another.
*
* In the rare case you don't want to queue the any {@link ViewAction} but rather execute it once only
* use {@link #ifViewAttached(ViewAction)}.
*
* @author Hannes Dorfmann
* @since 3.1.0
*/
public class MvpQueuingBasePresenter<V extends MvpView> implements MvpPresenter<V> {

/**
* An Action that is executed to interact with the view.
* Usually a Presenter should not get any data from View: so calls like view.getUserId() should
* not be done.
* Rather write a method in your Presenter that takes the user id as parameter like this:
* {@code
* void doSomething(int userId){
* // do something
* ...
*
* ifViewAtached( view -> view.showSuccessful())
* }
*
* @param <V> The Type of the View
*/
public interface ViewAction<V> {
/**
* An Action that is executed to interact with the view.
* Usually a Presenter should not get any data from View: so calls like view.getUserId() should
* not be done.
* Rather write a method in your Presenter that takes the user id as parameter like this:
* {@code
* void doSomething(int userId){
* // do something
* ...
* <p>
* ifViewAttached( view -> view.showSuccessful())
* }
*
* @param <V> The Type of the View
*/
public interface ViewAction<V> {

/**
* This method will be invoked to run the action. Implement this method to interact with the
* view.
*
* @param view The reference to the view. Not null.
*/
void run(@NonNull V view);
}

private Queue<ViewAction<V>> viewActionQueue = new ConcurrentLinkedQueue<>();

private WeakReference<V> viewRef;

private boolean presenterDestroyed;

/**
* {@inheritDoc}
*/
@Override
public void attachView(@NonNull V view) {
presenterDestroyed = false;
viewRef = new WeakReference<V>(view);
runQueuedActions();
}

/**
* {@inheritDoc}
*/
@Deprecated
@Override
public void detachView(boolean retainInstance) {
}

/**
* {@inheritDoc}
*/
@Override
public void detachView() {
viewRef.clear();
}

/**
* This method will be invoked to run the action. Implement this method to interact with the
* view.
* {@inheritDoc}
*/
@Override
public void destroy() {
viewActionQueue.clear();
presenterDestroyed = false;
}

/**
* If the view is attached, the view action is run immediately.
* If view is not attached, the action will be put in a queue. Once a view is attached, each
* action will be polled from the queue and executed one after another.
* <p>
* You have to call this method from Android's main UI thread.
*
* @param view The reference to the view. Not null.
* @param action The action that should run to interact with the view
*/
void run(@NonNull V view);
}

private Queue<ViewAction<V>> viewActionQueue = new ConcurrentLinkedQueue<>();

private WeakReference<V> viewRef;

private boolean presenterDestroyed;

/**
* {@inheritDoc}
*/
@Override public void attachView(@NonNull V view) {
presenterDestroyed = false;
viewRef = new WeakReference<V>(view);
runQueuedActions();
}

/**
* {@inheritDoc}
*/
@Deprecated @Override public void detachView(boolean retainInstance) {
}

/**
* {@inheritDoc}
*/
@Override public void detachView() {
viewRef.clear();
}

/**
* {@inheritDoc}
*/
@Override public void destroy() {
viewActionQueue.clear();
presenterDestroyed = false;
}

/**
* If the view is attached, the view action is run immediately.
* If view is not attached, the action will be put in a queue. Once a view is attached, each
* action will be polled from the queue and executed one after another.
*
* You have to call this method from Android's main UI thread.
*
* @param action The action that should run to interact with the view
*/
@MainThread protected final void onceViewAttached(ViewAction<V> action) {
viewActionQueue.add(action);
runQueuedActions();
}

/**
* Runs the queued actions.
*/
private void runQueuedActions() {
V view = viewRef == null ? null : viewRef.get();
if (view != null) {
while (!viewActionQueue.isEmpty()) {
ViewAction<V> action = viewActionQueue.poll();
action.run(view);
}
@MainThread
protected final void onceViewAttached(ViewAction<V> action) {
viewActionQueue.add(action);
runQueuedActions();
}
}


/**
* Executes the passed Action only if a View is attached.
* if no view is attached either an exception will be thrown if parameter
* exceptionIfViewNotAttached is true. Otherwise, the action is just not executed (no exception
* thrown).
* Note that if no view is attached this will not re-executed the given action if the View get's
* re attached. If you want to do that use {@link #onceViewAttached(ViewAction)}
*
* @param exceptionIfViewNotAttached true, if an exception should be thrown if no view is
* attached
* while trying to execute the action. false, if no exception should be thrown (but action will
* not executed either since no view attached)
* @param action The {@link ViewAction} that will be exceuted if a view is attached. Here is
* where
* you call view.isLoading etc. Use the view reference passed as parameter to {@link
* ViewAction#run(Object)}.
*/
@MainThread
protected final void ifViewAttached(boolean exceptionIfViewNotAttached, ViewAction<V> action) {
final V view = viewRef == null ? null : viewRef.get();
if (view != null) {
action.run(view);
} else if (exceptionIfViewNotAttached) {
throw new IllegalStateException(
"No View attached to Presenter. Presenter destroyed = " + presenterDestroyed);

/**
* Runs the queued actions.
*/
private void runQueuedActions() {
V view = viewRef == null ? null : viewRef.get();
if (view != null) {
while (!viewActionQueue.isEmpty()) {
ViewAction<V> action = viewActionQueue.poll();
action.run(view);
}
}
}
}

/**
* Executes the passed Action only if a View is attached.
* if no view is attached either an exception will be thrown if parameter
* exceptionIfViewNotAttached is true. Otherwise, the action is just not executed (no exception
* thrown).
* Note that if no view is attached this will not re-executed the given action if the View get's
* re attached. If you want to do that use {@link #onceViewAttached(ViewAction)}
*
* @param exceptionIfViewNotAttached true, if an exception should be thrown if no view is
* attached
* while trying to execute the action. false, if no exception should be thrown (but action will
* not executed either since no view attached)
* @param action The {@link ViewAction} that will be exceuted if a view is attached. Here is
* where
* you call view.isLoading etc. Use the view reference passed as parameter to {@link
* ViewAction#run(Object)}.
*/
@MainThread
protected final void ifViewAttached(boolean exceptionIfViewNotAttached, ViewAction<V> action) {
final V view = viewRef == null ? null : viewRef.get();
if (view != null) {
action.run(view);
} else if (exceptionIfViewNotAttached) {
throw new IllegalStateException(
"No View attached to Presenter. Presenter destroyed = " + presenterDestroyed);
}
}

/**
* Calls {@link #ifViewAttached(boolean, ViewAction)} with false as first parameter (don't throw
* exception if view not attached).
*
* @see #ifViewAttached(boolean, ViewAction)
*/
protected final void ifViewAttached(ViewAction<V> action) {
ifViewAttached(false, action);
}

/**
* Calls {@link #ifViewAttached(boolean, ViewAction)} with false as first parameter (don't throw
* exception if view not attached).
*
* @see #ifViewAttached(boolean, ViewAction)
*/
protected final void ifViewAttached(ViewAction<V> action) {
ifViewAttached(false, action);
}


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
* // do something
* ...
*
* ifViewAtached( view -> view.showSuccessful())
* ifViewAttached( view -> view.showSuccessful())
* }
*
* }
Expand All @@ -54,7 +54,7 @@ public class MvpBasePresenter<V extends MvpView> implements MvpPresenter<V> {
* // do something
* ...
*
* ifViewAtached( view -> view.showSuccessful())
* ifViewAttached( view -> view.showSuccessful())
* }
* @param <V> The Type of the View
*/
Expand Down Expand Up @@ -114,7 +114,7 @@ public interface ViewAction<V> {
* attached
* while trying to execute the action. false, if no exception should be thrown (but action will
* not executed either since no view attached)
* @param action The {@link ViewAction} that will be exceuted if a view is attached. Here is
* @param action The {@link ViewAction} that will be executed if a view is attached. Here is
* where
* you call view.isLoading etc. Use the view reference passed as parameter to {@link
* ViewAction#run(Object)} and not deprecated method {@link #getView()}
Expand Down

0 comments on commit fcfefec

Please sign in to comment.