https://github.com/polidea/state-machine-android
A lightweight state machine implementation for Android.
https://github.com/polidea/state-machine-android
Last synced: about 1 year ago
JSON representation
A lightweight state machine implementation for Android.
- Host: GitHub
- URL: https://github.com/polidea/state-machine-android
- Owner: Polidea
- License: mit
- Created: 2015-07-08T11:08:07.000Z (about 11 years ago)
- Default Branch: master
- Last Pushed: 2015-07-08T12:48:38.000Z (about 11 years ago)
- Last Synced: 2023-04-01T06:23:05.342Z (over 3 years ago)
- Language: Java
- Size: 219 KB
- Stars: 24
- Watchers: 14
- Forks: 5
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# State Machine for Android
A lightweight state machine implementation for Android.
## Download
Via gradle. In main build.gradle :
```gradle
allprojects {
repositories {
...
maven {
url "https://oss.sonatype.org/content/repositories/snapshots"
}
}
}
```
Add library:
```gradle
compile 'com.polidea:statemachine:1.0.0-SNAPSHOT'
```
or Maven. Add plugin repository:
```xml
https://oss.sonatype.org/content/repositories/snapshots/
true
```
Add library:
```xml
com.polidea
statemachine
1.0.0-SNAPSHOT
```
**It is a stable version of library**
## Usage
### Creating custom BaseStateableHandler
The easiest way to use StateMachine is to extend `BaseStateableHandler`. It have 4 main methods that we should override:
* `getStateProvider()` - used by State's to get data from our Fragment/Activity. Base StateProvider contains one method `provideContext()`
* `getActionInterface()` - used by State's to perform action's on Activity/Fragment, e.g. show Toast.
* `getInitialStateClass()` - initial state class for `StateMachine`. By default it returns `InitialState` class.
* `onStateMachineDescribe(StateMachine stateMachine)` - here we should describe transitions between states in our `StateMachine`. Each transition is a set of: from class, to class, event id. It means: when current state is 'from state' and it will propagate 'event id' then state machine should go to 'to state'.
Sample `BaseStateableHandler`:
```java
public class LoginStateableHandler extends BaseStateableHandler implements LoginProvider, LoginActionInterface {
@Override
public LoginProvider getStateProvider() {
return this;
}
@Override
public LoginActionInterface getActionInterface() {
return this;
}
@Override
public int provideFragmentContainerId() {
return R.id.fragment_container;
}
@Override
public void onStateMachineDescribe(StateMachine stateMachine) {
stateMachine.addTransitionFromClass(LoginInitialState.class, LoginEvents.START_LOGIN, OnGoingLoginState.class);
stateMachine.addTransitionFromClass(OnGoingLoginState.class, LoginEvents.CANCELLED, LoginInitialState.class);
stateMachine.addTransitionFromClass(OnGoingLoginState.class, LoginEvents.SENDING_IN_PROGRESS, WaitingForLoginRequestState.class);
stateMachine.addTransitionFromClass(WaitingForLoginRequestState.class, LoginEvents.FINISHED, InitialState.class);
}
@Override
public Class extends State> getInitialStateClass() {
return LoginInitialState.class;
}
...
}
```
As you can see here, state machine contains 3 states: `LoginInitialState`, `OnGoingLoginState` and `WaitingForLoginRequestState`. Initial state is `LoginInitialState`. Looking at one of transition:
```java
stateMachine.addTransitionFromClass(LoginInitialState.class, LoginEvents.START_LOGIN, OnGoingLoginState.class);
```
means that, when state machine is in `LoginInitialState` and that state will fire `LoginEvents.START_LOGIN` event, then state machine should go to state `OnGoingLoginState`.
### Starting custom BaseStateableHandler
To make `LoginStateableHandler` work, you must remember to call it's `onCreate(Bundle savedInstanceState)`, `onResume()`, `onPause()`, `onSaveInstanceState(Bundle outState)` methods in appropriate Fragment/Activity lifecycle method's. Sample usage:
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
handler = new LoginStateableHandler();
handler.onCreate(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
handler.onResume();
}
@Override
protected void onPause() {
super.onPause();
handler.onPause();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
handler.onSaveInstanceState(outState);
}
```
Of course you can initialize handler from other places, not only Fragment/Activity. Here is an example of starting handler in singleton class like `Application`:
```java
public class MyApplication extends Application {
LoginStateableHandler handler;
@Override
public void onCreate() {
super.onCreate();
handler = new LoginStateableHandler();
handler.onCreate(null);
handler.onResume();
}
}
```
### Creating states
State machine consist of states. Each state should extends `State` that contains two methods:
* `onStateApplied()` - called when entering state
* `onStateLeft()` - called when leaving state
Each state should call `fireEvent(int eventId)` when it finish it's job. Sample `State`:
```java
public class OnGoingLoginState extends State{
@Inject
Bus bus;
@Inject
NetworkManager networkManager;
public OnGoingLoginState() {
Application.getComponentInstance().inject(this);
}
@Override
public void onStateApplied() {
bus.register(this);
}
@Override
public void onStateLeft() {
bus.unregister(this);
}
@Subscribe
public void onBusLoginEvent(BusLoginEvent loginEvent) {
networkManager.loginUser(loginEvent.getEmail(), loginEvent.getPassword());
fireEvent(LoginEvents.SENDING_IN_PROGRESS);
}
}
```
It is nice to use some Bus implementation, like [EventBus](https://github.com/greenrobot/EventBus) or [Otto](https://github.com/square/otto), to receive applications events.
In that example we use [Otto](https://github.com/square/otto) for sending `BusLoginEvent` (it may be send by activity when 'Login' button tapped) and receiving that event in `OnGoingLoginState`.
## Used libraries
* **[otto]** https://github.com/square/otto
* **[dagger 2]** https://github.com/google/dagger
* **[spock]** https://code.google.com/p/spock/
* **[android support library v7]**
## LICENSE
[LICENSE](./LICENSE)