Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ android:
- build-tools-23.0.3

# The SDK version used to compile your project
- android-23
- android-24

# Additional components
- extra-google-m2repository
Expand All @@ -31,7 +31,7 @@ android:
script: "./gradlew build"

jdk:
- oraclejdk7
- oraclejdk8

env:
- TERM=dumb
Expand Down
6 changes: 5 additions & 1 deletion ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
Version: 3.0
Version: 3.0.1
* Fix issue that interim navigation pages are not popped out on back navgation correctly
* Uplift target compile SDK to 24.

Version: 3.0.0
* View and Controller are one to one mapped
* FragmentController introduced that is bound with the same lifecycle as MvcFragment. It is easier to act as a presenter of fragment
* Able to post actions to ui thread from controllers by protected uiThreadRunner field
Expand Down
325 changes: 148 additions & 177 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,14 @@ ext {
version = [
major: 3,
minor: 0,
patch : 0
patch : 1
]
libGroup = 'com.shipdream'
libVersion = "${version.major}.${version.minor}.${version.patch}"
shouldPublish = false

androidMinSdkVersion = 14
androidCompileSdkVersion = 23
androidCompileSdkVersion = 24
androidBuildToolVersion = "23.0.3"
supportLibVersion = "24.0.0"
androidTargetSdkVersion = androidCompileSdkVersion
Expand Down
Binary file removed documents/imgs/Android-Mvc-Pattern.jpg
Binary file not shown.
2 changes: 1 addition & 1 deletion extension/service-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

plugins {
id "com.jfrog.bintray" version "1.4"
id "com.jfrog.bintray" version "1.7"
}

apply plugin: 'java'
Expand Down
2 changes: 1 addition & 1 deletion library/android-mvc-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

plugins {
id "com.jfrog.bintray" version "1.4"
id "com.jfrog.bintray" version "1.7"
}

apply plugin: 'java'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright 2016 Kejun Xia
*
* 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.
*/

package com.shipdream.lib.android.mvc;

import com.shipdream.lib.android.mvc.event.bus.EventBus;
Expand All @@ -14,22 +30,61 @@
import javax.inject.Inject;

/**
* Abstract view controller. Presenter will subscribe to {@link EventBusC}
* <p>
* A controller is a delegate of a Android view. It holds a {@link UiView} that needs to be implemented
* by the corresponding Android view. Whenever the controller changes its model, it calls {@link UiView#update()}
* to update the view. Be careful when you are calling {@link UiView#update()} on the non-UI thread,
* because in this case, it needs to use {@link #uiThreadRunner} to post a runnable wrapping
* {@link UiView#update()} to ensure the view is updated on UI thread. Use {@link #runTask(Task)} to
* run heavy actions, especially network calls, on non-UI thread.
* </p>
*
* <p>
* In the above way the controller works as a presenter in MVP pattern. If you prefer MVVM pattern.
* You can define events and {@link #postEvent(Object)} to the view. Since {@link #postEvent(Object)}
* guarantees the event is posted onto UI thread, you don't need to worry about on which thread the
* event is posted.
* </p>
*
* <p>
* When some code needs to run on non-UI thread, use {@link #runTask(Task)},
* {@link #runTask(Task, Task.Callback)} to run it on a different thread. Make sure if
* {@link UiView#update()} needs to be called in scope of @link Task#execute(Task.Monitor)} use
* {@link #uiThreadRunner} to post back to UI thread.
* </p>
*
* <p>
* The controller has 4 injected fields. They can be replaced by providing special or mocking objects
* in unit tests.
* <ul>
* <li>a {@link EventBus} annotated by {@link EventBusC} to receive events from managers and other non ui components</li>
* <li>a {@link EventBus} annotated by {@link EventBusV} to send event to Android views</li>
* <li>a {@link ExecutorService} that runs {@link Task} via {@link #runTask(Task)} on non-UI thread.
* by default, it has a fixed thread tool at size 10. You can inject a mocked {@link ExecutorService}
* that runs everything on the main thread in your <b>Unit Tests</b> to avoid multi-thread complexity.</li>
* <li>a protected {@link UiThreadRunner} to post a {@link Runnable} onto UI thread. Make sure
* use it to {@link UiView#update()} view inside method block {@link Task#execute(Task.Monitor)}
* which is run on non-UI thread. It's NOT necessary to use it in callback methods in
* {@link Task.Callback} since the framework has already guaranteed it.
* In non-Android environment, typically in unit tests, the framework will also provide a default
* uiThreadRunner that runs everything on the same thread as the caller's.</li>
* </ul>
* </p>
* @param <MODEL> The view model of the controller.
*/
public abstract class Controller<MODEL, VIEW extends UiView> extends Bean<MODEL> {
protected VIEW view;

@Inject
@EventBusC
private EventBus eventBus2C;
private EventBus eventBusC;

@Inject
@EventBusV
private EventBus eventBus2V;
private EventBus eventBusV;

@Inject
protected ExecutorService executorService;
private ExecutorService executorService;

@Inject
protected UiThreadRunner uiThreadRunner;
Expand All @@ -51,7 +106,7 @@ public void onCreated() {
uiThreadRunner = Mvc.graph().uiThreadRunner;
}

eventBus2C.register(this);
eventBusC.register(this);
}

/**
Expand All @@ -61,7 +116,7 @@ public void onCreated() {
@Override
public void onDestroy() {
super.onDestroy();
eventBus2C.unregister(this);
eventBusC.unregister(this);
}

/**
Expand Down Expand Up @@ -254,16 +309,63 @@ public void run() {
}

/**
* <p>
* Post the event to views. It automatically guarantees the event will be received
* and run on UI thread of Android
* and run on UI thread of Android.
* </p>
*
* <p>
* The event will be captured by views or any objects registered to {@link EventBus} annotated
* by {@link EventBusV} and has corresponding method named onEvent() with single parameter with
* the same type of the event. For example
* </p>
* <pre>
* public class OnTextChangedEvent {
* private String text;
*
* public OnTextChangedEvent(String text) {
* this.text = text;
* }
*
* public String getText() {
* return text;
* }
* }
*
* public class SomeView {
* @ Inject
* @ EventBusV
* private EventBus eventBusV;
*
* private TextView textView;
*
* public class SomeView() {
* //This is just needed when you have a view not inheriting MvcFragment, MvcService or etc.
* //In MvcFragment or MvcService will register to the event bus in onCreate automatically.
* eventBusV.register(this);
* }
*
* public void onEvent(OnTextChangedEvent onTextChangedEvent) {
* textView.setText(onTextChangedEvent.getText());
* }
* }
*
* public class SomeController{
* private void func() {
* postEvent(new OnTextChangedEvent("Controller Wants to change text"));
* }
* }
* </pre>
*
* @param eventV The event
*/
protected void postEvent(final Object eventV) {
uiThreadRunner.post(new Runnable() {
@Override
public void run() {
eventBus2V.post(eventV);
eventBusV.post(eventV);
}
});
}

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
/*
* Copyright 2016 Kejun Xia
*
* 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.
*/

package com.shipdream.lib.android.mvc;

import org.jetbrains.annotations.NotNull;

/**
* Configuration of forwarding navigation by setting
* <ul>
* <li>{@link #setInterim(boolean)}</li>
* <li>{@link #clearTo(String)}</li>
* <li>{@link #setInterim(boolean)} indicating whether the location currently navigating to will
* be an interim in the navigation history, which means when {@link Navigator#back()} is called
* the interim locations will be skipped.</li>
* <li>{@link #clearTo(Class)} </li>
* <li>{@link #clearAll()}</li>
* </ul>
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright 2016 Kejun Xia
*
* 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.
*/

package com.shipdream.lib.android.mvc;

public abstract class FragmentController<MODEL, VIEW extends UiView> extends Controller<MODEL, VIEW>{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright 2016 Kejun Xia
*
* 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.
*/

package com.shipdream.lib.android.mvc;


Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright 2016 Kejun Xia
*
* 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.
*/

package com.shipdream.lib.android.mvc;

import com.shipdream.lib.poke.Component;
Expand Down Expand Up @@ -26,6 +42,11 @@
*/
public class MvcComponent extends Component {
private Logger logger = LoggerFactory.getLogger(getClass());

/**
* Name of the component
* @param name
*/
public MvcComponent(String name) {
super(name);
}
Expand Down
Loading