Skip to content
This repository has been archived by the owner on Mar 16, 2021. It is now read-only.

TiPresenter#runOnUiThread(Runnable) #65

Merged
merged 14 commits into from
Feb 10, 2017
Merged

TiPresenter#runOnUiThread(Runnable) #65

merged 14 commits into from
Feb 10, 2017

Conversation

passsy
Copy link
Contributor

@passsy passsy commented Jan 27, 2017

Allows code to run on the UI thread within the TiPresenter. This is most likely not a method for users of Ti but for extensions using the LifecycleObserver-API (another PR will follow).

public API changes

The action of TiPresenter#sendToView(Runnable action) will be now be called on the UI thread. Furthermore will those actions be executed after onAttachView(TiView) and after all lifecycle observers have been called. This allows preparing the view in onAttachView(TiView) for those actions. That way the view should be in a "running" state as if the view was never gone.
For very rare and special cases TiPresenter#getQueuedViewActions() can be used to manually execute queued actions. People are creative.

Another change has been made to RxTiPresenterUtils#isViewReady() which was firing the ready event before onAttachView(TiView) was called. The ready event is now fired after onAttachView(TiView)

The execution order of lifecycle obersvers when receiving teardown events has been reversed; following "first in, last out"

internal changes

The method in DelegatedTiActivity#postToMessageQueue(Runnable runnable) has been replaced with DelegatedTiActivity#Executor getUiThreadExecutor();, same for the Fragment interface. All classes have been adjusted.


I think the API changes are not critical and could also be bug fixes preventing rare race conditions.

@@ -73,6 +75,11 @@ public P getPresenter() {
return mDelegate.getPresenter();
}

@Override
public Executor getUiThreadExecutor() {
return new UiThreadExecutor();
Copy link

@albrecht87 albrecht87 Jan 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without knowing the exact context an understanding question: is it necessary to always create a new UiThreadExecutor ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's harder to leak an Activity when the Executor isn't static or reused. Also it's a very small class, shouldn't cause problems

/**
* Runs the specified action on the UI thread. It only works when a view is attached
* <p>
* When you are looking for a way to execute code when the view is attached have a look
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you are looking for a way to execute code when the view got available sometime in the future [...]

* @param action the action to run on the UI thread
* @throws IllegalStateException when the executor is not available
*/
public void runOnUiThread(@NonNull final Runnable action) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add some tests for this method.
Also when it is not really usable for "users"... But it is public. So we need to take care of it.

Also thinking about to make it just protected... Isn't it enough? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, first of all I want an overall acceptance before I invest time to test his approach

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cannot be protected because the View implementer (Activity via delegate) has to set it, therefore it has to be public because they live in a different package.

private final Executor mUiThreadExecutor;

public UiThreadExecutorAutoBinder(final TiPresenter presenter,
final Executor uiThreadExecutor) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we expect a UiThreadExecutor, then change the Executor signature to it.
Otherwise we can put any Executor to it which isn't on the UiThread.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would break our compatibility with JVM tests. The delegates and all used interfaces are android classes free. The UiThreadExecutor is 100% Android related.

@@ -33,6 +35,11 @@
P getRetainedPresenter();

/**
* @return {@link UiThreadExecutor}
*/
Executor getUiThreadExecutor();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same like the AutoBinder. Change it to UiTheadExecutor as return value...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

breaks JVM tests

// reverse observer order for teardown events; first in, last out
for (int i = mLifecycleObservers.size() - 1; i >= 0; i--) {
mLifecycleObservers.get(i).onChange(newState, hasLifecycleMethodBeenCalled);
}
Copy link
Contributor Author

@passsy passsy Feb 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • add tests for correct call oder

@passsy
Copy link
Contributor Author

passsy commented Feb 6, 2017

@StefMa Ready. I already tested the sample and a real project and everything works fine

@StefMa StefMa merged commit 9d41ece into master Feb 10, 2017
@StefMa StefMa deleted the feature/runonmainthread branch February 10, 2017 10:20
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

Successfully merging this pull request may close these issues.

3 participants