<commit_before>#Pilot

An abstract application stack which facilitates:

- Presenter lifecycle management
- Presenter -> Presenter control flow
- Fine grained data scope management
- Presenter lifecycle events
- A `View` based architecture 

![Pilot Mascot](https://raw.githubusercontent.com/doridori/Pilot/master/gfx/pilot_mascot.png)

**Note this is a WIP**

If you have not already I **highly recommened** you read the `Motivations` post found [here](http://doridori.github.io/Android-Architecture-Pilot/) as they lay a foundation for the solutions presented in this README.

This README will have the following structure:

1. Quick Intro to the project
2. Some short usage examples
3. Outline the core library components
4. Outline the general concepts
5. How to integrate
6. Highlight what still needs to be worked on
7. Mention any current known limitations

#Intro

**Pilot** is an effort to abstract a simple Application Stack from the common approaches to Controller/Presenter (from now on I will just use these terms interchangeably) based Android application architecture. An aim is to **not** tie any implementations to any specifc controller type or 3rd party dependencies i.e. to be as flexible as possible. I often use State-based Presenter (as outlined by [Dynamo](https://github.com/doridori/Dynamo)) but this is by no mean a requirement.

This is _somewhat like_ a `FragmentManager` for `Views` but it is also much more than that. It is **Presenter-aware**, simple in implementation, has plumbing to handle `View` creation and **Presenter mapping** out of the box (which is optional and can be used to trigger Fragment/Activity transitions also), **survives config-changes and process-death** and has a **queryable** app stack **which can hold scoped data** as well as view-backing-presenters. 

You may read the below and think _'thats what `FragmentManager` is for'_ or _'I use the Activity backstack for that'_ and if you find those solutions are working for you thats great. I find that there is often cases where these two api concepts either over-complicate or restrict the things I need to do and feel there is a good case for some applications to use an abstracted stack instead.

This approach is something like a micro-framework as the application navigation flows through and is handled by it. It also is an approach to building apps that makes the problems outlined by the discussed motivations easier to handle but is not a library that has been created to solve a specific individual issue.

Pilot can be used in single-Activity applications (recommened!) or one-per Activity if need be.

#Quick Usage Examples

Quick setup in your applications Root Activity (I find I only use one Activity per app) by specifing an array of `@Presenter` backed `View` classes and the app launch state.

```java
public class ExampleRootActivity extends Activity
{
    private static PilotManager sPilotManager;

    static
    {
        Class<? extends PresenterBasedFrameLayout>[] rootViews = new Class[]{
                FirstView.class,
                SecondInSessionView.class
        };

        sPilotManager = new PilotManager(rootViews, FirstViewPresenter.class);
    }
    ...
}
```

_Im sure you may be thinking uh-oh when you see the `static`s above. This is explained elsewhere in this README._ 

Delegate some `Activity` lifecycle calls to the `PilotManager`

```java
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        FrameLayout rootView = new FrameLayout(this);
        setContentView(rootView);
        sPilotManager.onCreateDelegate(savedInstanceState, rootView, this);
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        sPilotManager.onDestroyDelegate(this);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState)
    {
        super.onSaveInstanceState(outState);
        sPilotManager.onSaveInstanceStateDelegate(outState);
    }

    @Override
    public void onBackPressed()
    {
        sPilotManager.onBackPressedDelegate();
    }
```

The first time `Activity.onCreate()` is called it will triggers the `FirstView` to be added to the rootView (declared above), with access to its Presenter (as defined by `@Presenter`) which is pulled (and itself has access to) from the Activitys `PilotStack`.

```java
@Presenter(FirstViewPresenter.class)
public class FirstView extends PresenterBasedFrameLayout<FirstViewPresenter>
{
    ...
    public void someButtonPressed()
    {
        getPresenter().someButtonPressed();
    }
}
```

Example of view action causing a presenter method to be called, which in turn manipulates the application stack directly. This could just as easily have originated from internal logic to the presenter i.e. as the result of some asyncronous operation. This examples pushes a data-frame on the stack also (more on that later). Note how **no** `android.*` classes are involved in this app navigation / state transition.

```java
/**
 * Implement the Presenter/Controller aspect of this whatever way you want
 */ 
public class FirstViewPresenter extends PilotFrame
{
    ...
    /**
     * This represents some app nav action which happens via the parent FatStack.
     * Called by UI in production or called directly in tests. At this point you will generally want to
     *
     * 1) push another UI frame on the stack
     * 2) push a scoped-data frame on the stack and then a UI frame.
     */
    public void someButtonPressed()
    {
        //example of pushing data frame then presenter frame *directly* from presenter
        getParentStack().pushFrame(new SessionScopedData("RandomSessionKey"));
        getParentStack().pushFrame(new SecondInSessionViewPresenter());
    }
}
```

The corresponding view that utilised the newly added Presenter will auto be added to the main rootView (and all other Views removed).

```java
@Presenter(SecondInSessionViewPresenter.class)
public class SecondInSessionView extends PresenterBasedFrameLayout<SecondInSessionViewPresenter>
{
    public void someFuntionality()
    {
        getPresenter().someMethodCall...
    }
}
```

Pretty simple but quite powerful!

#Core Components

##The `PilotStack`

The `PilotStack` is the main core of this mini library which has the following properties:

- Holds an internal collection of `PilotFrame` objects that can be manipulated in various ways (Push, Pop, Clear at frame, clear all).
- Stack events can be listened to
- Implements `Serializable`

##The `PilotFrame`

- Has lifecycle methods
- Holds reference to parent stack
- Implements `Serializable`

**The `PilotFrame` can also be a controller itself or hold a reference to one.**

##The `@InvisibleFrame`

Annotation that can be applied to a `PilotFrame` subclass which signifies that it should be ignored for all stack callback operations. Very useful for handling scoped data within the stack

##The `PresenterBasedFrameLayout`

Base [class](https://github.com/doridori/Pilot/blob/master/android/lib/app/src/main/java/com/kodroid/pilot/lib/android/PresenterBasedFrameLayout.java) that can be extended for RichViews which accepts Presenter setting. Needs a [`@Presenter`](https://github.com/doridori/Pilot/blob/master/android/lib/app/src/main/java/com/kodroid/pilot/lib/android/Presenter.java) annotation to be present.

##The `PilotManager`

Handles a `PilotStack` for you and handles core `View` changes based upon stack transitions (if you are using Views). A `PilotManager` is intended to be used one-per-Activity and is designed to be referenced and setup statically as it handles its own memory releasing inside the Activity lifecycle delegate calls. This allows for easy persistence accross config-changes and back-stack-memory-saving-death and will clear all memory used when the Activity is destroyed for good. It will also handle saving and restoring itself on process-death. For a any discussion or questions about this please see [this related ticket](https://github.com/doridori/Pilot/issues/8). **Think of the `PilotManager` as the glue code between Android `Activity`s lifecycle peculiarities / View handling and the simple `PilotStack` functionality and usefullness.**

The `PilotManager` allows you to _compose_ your Activity with Pilot functionality as opposed to _inherit_ it from some form of PilotRootActivity, hence the need for delegation methods.

#General Concepts

##Single-Activity Application

I find a lot of the applications I have build in the last couple of years sit inside a single `Activity` and just manipulate `Fragments` and/or `View`. You can use a single `Activity` which holds a single `PilotStack` for the simplest use case. This however does not mean you cant jump out to seperate activitys, for example when integrating with 3rd party libs which require this.

Advantage: Simple

##Presenter-to-Presenter control flow

As mentioned in the `Motivations` post above this kind of control flow (which bypasses `android.*` classes completly has its advantages) and is made very simple with Pilot. An example below<commit_msg>formatting<commit_after>#Pilot

An abstract application stack which facilitates:

- Presenter lifecycle management
- Presenter -> Presenter control flow
- Fine grained data scope management
- Presenter lifecycle events
- A `View` based architecture 

![Pilot Mascot](https://raw.githubusercontent.com/doridori/Pilot/master/gfx/pilot_mascot.png)

**Note this is a WIP**

If you have not already I **highly recommened** you read the `Motivations` post found [here](http://doridori.github.io/Android-Architecture-Pilot/) as they lay a foundation for the solutions presented in this README.

This README will have the following structure:

1. Quick Intro to the project
2. Some short usage examples
3. Outline the core library components
4. Outline the general concepts
5. How to integrate
6. Highlight what still needs to be worked on
7. Mention any current known limitations

#Intro

**Pilot** is an effort to abstract a simple Application Stack from the common approaches to Controller/Presenter (from now on I will just use these terms interchangeably) based Android application architecture. An aim is to **not** tie any implementations to any specifc controller type or 3rd party dependencies i.e. to be as flexible as possible. I often use State-based Presenter (as outlined by [Dynamo](https://github.com/doridori/Dynamo)) but this is by no mean a requirement.

This is _somewhat like_ a `FragmentManager` for `Views` but it is also much more than that. It is **Presenter-aware**, simple in implementation, has plumbing to handle `View` creation and **Presenter mapping** out of the box (which is optional and can be used to trigger Fragment/Activity transitions also), **survives config-changes and process-death** and has a **queryable** app stack **which can hold scoped data** as well as view-backing-presenters. 

You may read the below and think _'thats what `FragmentManager` is for'_ or _'I use the Activity backstack for that'_ and if you find those solutions are working for you thats great. I find that there is often cases where these two api concepts either over-complicate or restrict the things I need to do and feel there is a good case for some applications to use an abstracted stack instead.

This approach is something like a micro-framework as the application navigation flows through and is handled by it. It also is an approach to building apps that makes the problems outlined by the discussed motivations easier to handle but is not a library that has been created to solve a specific individual issue.

Pilot can be used in single-Activity applications (recommened!) or one-per Activity if need be.

#Quick Usage Examples

Quick setup in your applications Root Activity (I find I only use one Activity per app) by specifing an array of `@Presenter` backed `View` classes and the app launch state.

```java
public class ExampleRootActivity extends Activity
{
    private static PilotManager sPilotManager;

    static
    {
        Class<? extends PresenterBasedFrameLayout>[] rootViews = new Class[]{
                FirstView.class,
                SecondInSessionView.class
        };

        sPilotManager = new PilotManager(rootViews, FirstViewPresenter.class);
    }
    ...
}
```

_Im sure you may be thinking uh-oh when you see the `static`s above. This is explained elsewhere in this README._ 

Delegate some `Activity` lifecycle calls to the `PilotManager`

```java
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        FrameLayout rootView = new FrameLayout(this);
        setContentView(rootView);
        sPilotManager.onCreateDelegate(savedInstanceState, rootView, this);
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        sPilotManager.onDestroyDelegate(this);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState)
    {
        super.onSaveInstanceState(outState);
        sPilotManager.onSaveInstanceStateDelegate(outState);
    }

    @Override
    public void onBackPressed()
    {
        sPilotManager.onBackPressedDelegate();
    }
```

The first time `Activity.onCreate()` is called it will triggers the `FirstView` to be added to the rootView (declared above), with access to its Presenter (as defined by `@Presenter`) which is pulled (and itself has access to) from the Activitys `PilotStack`.

```java
@Presenter(FirstViewPresenter.class)
public class FirstView extends PresenterBasedFrameLayout<FirstViewPresenter>
{
    ...
    public void someButtonPressed()
    {
        getPresenter().someButtonPressed();
    }
}
```

Example of view action causing a presenter method to be called, which in turn manipulates the application stack directly. This could just as easily have originated from internal logic to the presenter i.e. as the result of some asyncronous operation. This examples pushes a data-frame on the stack also (more on that later). Note how **no** `android.*` classes are involved in this app navigation / state transition.

```java
/**
 * Implement the Presenter/Controller aspect of this whatever way you want
 */ 
public class FirstViewPresenter extends PilotFrame
{
    ...
    /**
     * This represents some app nav action which happens via the parent FatStack.
     * Called by UI in production or called directly in tests. At this point you will generally want to
     *
     * 1) push another UI frame on the stack
     * 2) push a scoped-data frame on the stack and then a UI frame.
     */
    public void someButtonPressed()
    {
        //example of pushing data frame then presenter frame *directly* from presenter
        getParentStack().pushFrame(new SessionScopedData("RandomSessionKey"));
        getParentStack().pushFrame(new SecondInSessionViewPresenter());
    }
}
```

The corresponding view that utilised the newly added Presenter will auto be added to the main rootView (and all other Views removed).

```java
@Presenter(SecondInSessionViewPresenter.class)
public class SecondInSessionView extends PresenterBasedFrameLayout<SecondInSessionViewPresenter>
{
    public void someFuntionality()
    {
        getPresenter().someMethodCall...
    }
}
```

Pretty simple but quite powerful!

#Core Components

##The `PilotStack`

The `PilotStack` is the main core of this mini library which has the following properties:

- Holds an internal collection of `PilotFrame` objects that can be manipulated in various ways (Push, Pop, Clear at frame, clear all).
- Stack events can be listened to
- Implements `Serializable`

##The `PilotFrame`

- Has lifecycle methods
- Holds reference to parent stack
- Implements `Serializable`

**The `PilotFrame` can also be a controller itself or hold a reference to one.**

##The `@InvisibleFrame`

Annotation that can be applied to a `PilotFrame` subclass which signifies that it should be ignored for all stack callback operations. Very useful for handling scoped data within the stack

##The `PresenterBasedFrameLayout`

Base [class](https://github.com/doridori/Pilot/blob/master/android/lib/app/src/main/java/com/kodroid/pilot/lib/android/PresenterBasedFrameLayout.java) that can be extended for RichViews which accepts Presenter setting. Needs a [`@Presenter`](https://github.com/doridori/Pilot/blob/master/android/lib/app/src/main/java/com/kodroid/pilot/lib/android/Presenter.java) annotation to be present.

##The `PilotManager`

Handles a `PilotStack` for you and handles core `View` changes based upon stack transitions (if you are using Views). A `PilotManager` is intended to be used one-per-Activity and is designed to be referenced and setup **statically** as it handles its own memory releasing inside the Activity lifecycle delegate calls. This allows for easy persistence accross config-changes and back-stack-memory-saving-death and will clear all memory used when the Activity is destroyed for good. It will also handle saving and restoring itself on process-death. For a any discussion or questions about this please see [this related ticket](https://github.com/doridori/Pilot/issues/8). **Think of the `PilotManager` as the glue code between Android `Activity`s lifecycle peculiarities / View handling and the simple `PilotStack` functionality and usefullness.**

The `PilotManager` allows you to _compose_ your Activity with Pilot functionality as opposed to _inherit_ it from some form of PilotRootActivity, hence the need for delegation methods.

#General Concepts

##Single-Activity Application

I find a lot of the applications I have build in the last couple of years sit inside a single `Activity` and just manipulate `Fragments` and/or `View`. You can use a single `Activity` which holds a single `PilotStack` for the simplest use case. This however does not mean you cant jump out to seperate activitys, for example when integrating with 3rd party libs which require this.

Advantage: Simple

##Presenter-to-Presenter control flow

As mentioned in the `Motivations` post above this kind of control flow (which bypasses `android.*` classes completly has its advantages) and is made very simple with Pilot. An example below
{'fraction_non_alphanumeric': 0.06690430490814368, 'fraction_numerical': 0.0013161502604880724, 'mean_word_length': 4.173333333333333, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 10, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2157772', 'n_tokens_mistral': 4836, 'n_tokens_neox': 4613, 'n_words': 2233}