<commit_before>BR Continuity - Android
============

### Purpose
This library provides a means to retain an object across Android UI lifecycle events for a specified amount of time after that UI object has been destroyed. The retained objects are keyed on combination of the type of the "anchor" (UI) object requesting it, the Android Task that the anchor exists in, the type of the continuous class, and an optional string tag. 

### Key Concepts
* Anchor - An object whose existence is used to determine whether to keep the ContinuousObject around.
* ContinuousObject - Any object that can optionally implement the ContinuousObject interface which you want to keep around across lifecycle events. 
* Tag - An optional arbitrary string that will generate a different ContainerId. 
* Android Task - The Android system keeps stacks of Activities in Tasks. For multi-window support two Activities of identical type could be visible at once belonging to two separate Tasks. 
* ContainerId - A combination of the canonical name of the Anchor, Android Task ID, canonical name of the ContinuousObject, and a Tag which uniquely identifies a ContinuousObject for storage and retrieval.
* Check Interval - Time in milliseconds between freshness checks to determine if an anchor object has been garbage collected. 
* Default Lifetime - Time in milliseconds to retain a ContinuousObject after all associated Anchor objects have been garbage collected. 
* Idle Shutdown - Time in milliseconds that the freshness check thread will run without any objects being accessed. After this time the thread will shut down until the next operation occurs. Objects in the repository will remain.
* Max Empty Iterations - If the repository is empty for this number of iterations, the freshness checking thread will shutdown until the next operation occurs.  
* ContinuityFactory - Generic Functional Interface that will create an object that requires constructor parameters.

### Usage
The ContinuityRepository object should be held in such a way that there is typically only one instance in use and that it outlives your Activities. You can use a Singleton to contain it, a DI framework, Service Locator, or whatever floats your boat. In the examples we'll just assume I have this Singleton-like instance at hand already.

#### Presenter
Create a presenter class somewhere and be sure it implements ContinuousObject if you want to be notified when it is being discarded. 

		public class MyPresenter implements ContinuousObject {
					
			//Do all the things you need to do in your presenter.
			
			@Override
			onContinuityDiscard() {
				//Disconnect anything you are observing, cancel operations, etc.
			}
		}

#### Activity
Now in your Activity whenever you are ready to get the object.

		@Override
		onCreate(@Nullable Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			//Inflate layouts, etc.
			
			//Use this Activity as the Anchor, and create or fetch an instance of MyPresenter
			MyPresenter myPresenter = continuityRepository.with(this, MyPresenter.class).build();
		}

That is it! The first time the Activity is created for a specific Android Task you will get a new instance. From that point onward until the Activity has been garbage collected for a specified amount of time, you will get the same MyPresenter Object.

#### Fragment
Fragments are a slightly different case. Because the Android Task ID is unknown until it is attached to the Activity, you have to use the onActivityCreated method to properly identify the Android Task. 

		@Override
		public void onActivityCreated(@Nullable Bundle savedInstanceState) {
	        super.onActivityCreated(savedInstanceState);
	        //Do anything else you need to do here.

			//Use this Fragment as the Anchor, and create or fetch an instance of MyPresenter
			MyPresenter myPresenter = continuityRepository.with(this, MyPresenter.class).build();
	    }
		
**NOTE:** This will not be the same instance that was provided to the Activity in the example above even if the Fragment is attached to that Activity. If you want them to receive the same Presenter(not recommended) pass the Activity instance as the Anchor for both calls. You shouldn't share Presenters or really any other object this way.

#### Changing Defaults
If the default timeouts are not acceptable, you can specify your own in the ContinuityRepository constructor. You can even have many ContinuousRepository instances with different timings, but that may become hard to manage. You can also override the lifetime of a single ContinuousObject by specifying a different lifetime in the builder. 

#### Builder Options
		
		final String testString = "test"; //Used later for the ExampleTestClass constructor.
		
		ExampleTestClass exampleTestClass = continuityRepository.with(this, ExampleTestClass.class)
			.task(1234)      //Provide an arbitrary task id instead of trying to obtain it from the Anchor
		    .lifetime(1000)  //Change the lifetime that this specific ContinuousObject should be retained
		    .using(new ContinuityFactory<ExampleTestClass>() {
               @Override
                public ExampleTestClass create() {
                    return new ExampleTestClass(testString);
                }
            })               //Use an anonymous ContinuityFactory if the constructor requires arguments.
            .tag("example1") //Further differentiate the ContainerId with a custom tag like an article Id.<commit_msg>Update README with onDestroy functionality<commit_after>BR Continuity - Android
============

### Purpose
This library provides a means to retain an object across Android UI lifecycle events for a specified amount of time after that UI object has been destroyed. The retained objects are keyed on combination of the type of the "anchor" (UI) object requesting it, the Android Task that the anchor exists in, the type of the continuous class, and an optional string tag. 

### Key Concepts
* Anchor - An object whose existence is used to determine whether to keep the ContinuousObject around.
* ContinuousObject - Any object that can optionally implement the ContinuousObject interface which you want to keep around across lifecycle events. 
* Tag - An optional arbitrary string that will generate a different ContainerId. 
* Android Task - The Android system keeps stacks of Activities in Tasks. For multi-window support two Activities of identical type could be visible at once belonging to two separate Tasks. 
* ContainerId - A combination of the canonical name of the Anchor, Android Task ID, canonical name of the ContinuousObject, and a Tag which uniquely identifies a ContinuousObject for storage and retrieval.
* Check Interval - Time in milliseconds between freshness checks to determine if an anchor object has been garbage collected. 
* Default Lifetime - Time in milliseconds to retain a ContinuousObject after all associated Anchor objects have been garbage collected. 
* Idle Shutdown - Time in milliseconds that the freshness check thread will run without any objects being accessed. After this time the thread will shut down until the next operation occurs. Objects in the repository will remain.
* Max Empty Iterations - If the repository is empty for this number of iterations, the freshness checking thread will shutdown until the next operation occurs.  
* ContinuityFactory - Generic Functional Interface that will create an object that requires constructor parameters.

### Usage
The ContinuityRepository object should be held in such a way that there is typically only one instance in use and that it outlives your Activities. You can use a Singleton to contain it, a DI framework, Service Locator, or whatever floats your boat. In the examples we'll just assume I have this Singleton-like instance at hand already.

#### Presenter
Create a presenter class somewhere and be sure it implements ContinuousObject if you want to be notified when it is being discarded. 

		public class MyPresenter implements ContinuousObject {
					
			//Do all the things you need to do in your presenter.
			
			@Override
			onContinuityDiscard() {
				//Disconnect anything you are observing, cancel operations, etc.
			}
		}

#### Activity
Now in your Activity whenever you are ready to get the object.

		@Override
		onCreate(@Nullable Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			//Inflate layouts, etc.
			
			//Use this Activity as the Anchor, and create or fetch an instance of MyPresenter
			MyPresenter myPresenter = continuityRepository.with(this, MyPresenter.class).build();
		}

That is it! The first time the Activity is created for a specific Android Task you will get a new instance. From that point onward until the Activity has been garbage collected for a specified amount of time, you will get the same MyPresenter Object.

#### Fragment
Fragments are a very slightly different case. You should wait until the result of getActivity() will not be null after onAttach() to ensure that the library can get the Activity's task id. 

        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            //Inflate layouts, etc.

            //Use this Fragment as the Anchor, and create or fetch an instance of MyPresenter
            MyPresenter myPresenter = continuityRepository.with(this, MyPresenter.class).build();
        }
		
**NOTE:** This will not be the same instance that was provided to the Activity in the example above even if the Fragment is attached to that Activity. If you want them to receive the same Presenter(not recommended) pass the Activity instance as the Anchor for both calls. You shouldn't share Presenters or really any other object this way.

#### Cleanup 
**IMPORTANT:** In your BaseActivity and BaseFragment or any one-off Fragments/DialogFragments it is a best practice to cleanup your anchor manually in the onDestroy method.

        @Override
        public void onDestroy() {
            super.onDestroy();
            continuityRepository.onDestroy(this);
        }

It is very easy to accidentally leak the UI by e.g. having the UI implement a Listener interface held by the Presenter. If you don't manually clean that Presenter->UI reference, it can leak the UI. 

        Singleton-ish(DI, ServiceLocator, Whatever) -> ContinuityRepository -> Presenter -> UI 
        
By calling ContinuityRepository.onDestroy(anchor) the ContinuityRepository->Presenter link will be broken **after** the lifetime has expired. It is still recommended that you notify your Presenter that your UI has been destroyed so that it can remove the listener reference and is not making calls against a dead UI element. This also expedites GC of the UI among countless other benefits.
	
#### Changing Defaults
If the default timeouts are not acceptable, you can specify your own in the ContinuityRepository constructor. You can even have many ContinuousRepository instances with different timings, but that may become hard to manage. You can also override the lifetime of a single ContinuousObject by specifying a different lifetime in the builder. 

#### Builder Options
		
		final String testString = "test"; //Used later for the ExampleTestClass constructor.
		
		ExampleTestClass exampleTestClass = continuityRepository.with(this, ExampleTestClass.class)
			.task(1234)      //Provide an arbitrary task id instead of trying to obtain it from the Anchor
		    .lifetime(1000)  //Change the lifetime that this specific ContinuousObject should be retained
		    .using(new ContinuityFactory<ExampleTestClass>() {
               @Override
                public ExampleTestClass create() {
                    return new ExampleTestClass(testString);
                }
            })               //Use an anonymous ContinuityFactory if the constructor requires arguments.
            .tag("example1") //Further differentiate the ContainerId with a custom tag like an article Id.
{'fraction_non_alphanumeric': 0.04568908122503329, 'fraction_numerical': 0.0014980026631158455, 'mean_word_length': 3.861245954692557, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 10, 'https://': 0, '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': '6971492', 'n_tokens_mistral': 2856, 'n_tokens_neox': 2582, 'n_words': 1580}