This repository has been archived by the owner on Dec 25, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from beworker/feature-lifecycle-inheritance
Feature lifecycle inheritance
- Loading branch information
Showing
32 changed files
with
1,052 additions
and
296 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Featured design | ||
Here is some rules and implementaiton details helping you to become familiar with the library and write cleaner code. | ||
- Features must not access other features directly but shall always interoperate through feature callbacks. By following this rule you will be rewarded with simple, maintainable and testable code later on. | ||
- You can define as many event callbacks as you need and they can have as many parameters as you need. | ||
- Generated feature host class will contain a `dispatchOn<Event>()` method for each feature's `on<Event>()` method. | ||
- To dispatch an event to all features you just need to call its corresponding `dispatchOn<Event>()`. | ||
- It is allowed to call a `dispatchOn<AnotherEvent>()` method from a feature's `on<Event>()` callback. Feature host will make sure that currently running dispatch loop finishes and current event gets dispatched to all features before the new event gets dispatched. | ||
- This make event dispatching to be asynchronous. It means you cannot assume that a `dispatchOn<Event>()` finishes, corresponding event has been delivered to all features. Actual event dispatching can happen also later in time. If you want to be notified after an event has been dispatched, you need to use `@FeatureEvent(dispatchCompleted = true)` and provide corresponding `OnDispatchCompleted` callback in `dispatchOn<Event>()` method. Provided callback will be notified after event dispatching finishes. | ||
- Current implementation is intended to be used in MainThread. This is the only thread strategy implemented at this time. | ||
- Featured is being actively developed and new library features are to be expected. |
File renamed without changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# Quick Start | ||
|
||
1) First you need to think of splitting your activity into independent components communicating via events. Start with standard activity or fragment lifecycle events like `onCreate()`, `onStart()` etc. and add other custome events like `onDataLoaded`, `onButtonClicked` etc. if required. | ||
|
||
2) Create a basis feature class and declare all lifecycle events in there. Use `@FeatureEvent` annotation for events to be dispatched. | ||
|
||
```java | ||
public class SampleFeature extends Feature<SampleFeatureHost, Context> { | ||
@FeatureEvent protected void onCreate(@NonNull CoordinatorLayout parent) { | ||
// nop | ||
} | ||
|
||
@FeatureEvent protected void onStart() { | ||
// nop | ||
} | ||
|
||
@FeatureEvent protected void onFabClicked() { | ||
// nop | ||
} | ||
|
||
@FeatureEvent protected void onStop() { | ||
// nop | ||
} | ||
|
||
@FeatureEvent protected void onDestroy() { | ||
// nop | ||
} | ||
} | ||
``` | ||
|
||
The `SampleFeature` class extends a parametrized `Feature` class. First parameter is the name of the feature host class to be generated. You can freely choose the name, but adding a `Host` string to the feature name is a good choice. Second parameter is a name of the context your feature is capable to access. It can be `Context`, `Activity`, `Fragment` or any other class you find usefull for your feature implementation. Later on, when you implement features you will be able to access this context from the feature code at any time. | ||
|
||
Build the project. `SampleFeatureHost` class will be generated and source code will compile successfully. | ||
|
||
3) Consider the `SampleFeature` class to be an interface defining feature lifecycle. Now you can implement your features by extending `SampleFeature` class as following: | ||
|
||
```java | ||
public class ToolbarFeature extends SampleFeature { | ||
@Override protected void onFabClicked() { | ||
// handle on-click-event here | ||
} | ||
} | ||
|
||
public class FabFeature extends SampleFeature implements View.OnClickListener { | ||
@Override public void onClick(View view) { | ||
// dispatch on-click-event to other features | ||
getFeatureHost().dispatchOnFabClicked(); | ||
} | ||
} | ||
``` | ||
|
||
Generated `SampleFeatureHost` class contains dispatch methods for each event method of the `SampleFeature`. Use these methods to dispatch events to your features. You can call those methods from the activity or from inside of any feature. | ||
|
||
4) Register features to the feature host class in your activity or a fragment. | ||
```java | ||
public MyFragment extends Fragment { | ||
private SampleFeatureHost mFeatureHost; | ||
|
||
@Override public void onCreate(Bundle savedInstanceState) { | ||
... | ||
CoordinatorLayout parent = (CoordinatorLayout) findViewById(R.id.coordinator); | ||
|
||
// create feature host and add a feature we created | ||
mFeatureHost = new SampleFeatureHost(getContext()) | ||
.with(new FabFeature()) | ||
.with(new ToolbarFeature()); | ||
|
||
// dispatch event to all registered features | ||
mFeatureHost.dispatchOnCreate(parent); | ||
} | ||
|
||
// dispatch other events correspondingly | ||
|
||
@Override public void onStart() { | ||
mFeatureHost.dispatchOnStart(); | ||
} | ||
|
||
@Override public void onStop() { | ||
mFeatureHost.dispatchOnStop(); | ||
} | ||
|
||
@Override public void onDestroy() { | ||
mFeatureHost.dispatchOnDestroy(); | ||
} | ||
} | ||
``` | ||
|
||
Your fragment become very simple and whole application code gets split into separated features with the very clean responcibilities. You can add new features or disable existing features depending on your use case or the device configuration etc. See `featured-sample` project for more code examples. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
featured-compiler/src/main/java/de/halfbit/featured/compiler/Assertions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package de.halfbit.featured.compiler; | ||
|
||
import de.halfbit.featured.compiler.model.FeatureNode; | ||
|
||
public class Assertions { | ||
|
||
private Assertions() { | ||
} | ||
|
||
public static <S> S assertNotNull(S subj, FeatureNode featureNode) { | ||
if (subj == null) { | ||
throw new IllegalArgumentException("Subject is null in " + featureNode); | ||
} | ||
return subj; | ||
} | ||
|
||
} |
Oops, something went wrong.