-
Notifications
You must be signed in to change notification settings - Fork 1
java_cache_contol
Provided objects in Stone are cached using various types of links. In some cases, when using objects, it is necessary to explicitly clean up the objects from DI.
The library supports object cleanup through the java garbage collection process. This means that if you explicitly plan to remove an object from the DI cache, you first need to get rid of the holders of that object. When the object is untied from everyone, the GC will independently collect it and destroy it.
DI allows you to explicitly call GC on different scopes. Each scope is defined by a scope annotation declared as follows:
@GcScopeAnnotation
@GcScopeAnnotation
@Retention(RUNTIME)
@Target(METHOD)
public @interface GcMercuryScope {
}Here we have declared @GcMercuryScope, which can be used when declaring object bindings and provisionings.
@Module
public interface PlanetsModule {
@GcMercuryScope
@BindInstance
Mercury mercury(Mercury sirius);
}Now we can clear the cache of this object.
By pre-declaring the cleanup method in the component using the @RunGc annotation
@Component
public interface PlanetsComponent {
PlanetsModule sunModule();
@RunGc
@GcMercuryScope
void gcMercury();
}By calling the DI.gcMercury() meta we will clean up the Mercury object if it is not held by anyone.
Also note that all cached weak reference objects will also be destroyed if they are not held by anyone.
The library also supports a set of standard scopes
-
@GcAllScope- all objects in the component -
@GcStrongScope- all objects in the component cached with a strong link -
@GcSoftScope- all objects in the component cached with a soft link -
@GcWeakScope- all objects in the component cached with a weak link. Equivalent to callingSystem.gc()
Multiple scopes can be used in one method to clean only the intersection of those scopes.
So the next method will clear Mercury objects cached only by soft link.
@Component
public interface PlanetsComponent {
@RunGc
@GcSoftScope
@GcMercuryScope
void gcSoftMercury();
}In addition to directly removing objects from DI, you can change the cache type using the @SwitchCache annotation.
Changing the cache type allows you to gradually remove unused objects from memory as their holders release them.
This may be necessary for the following purposes:
- If there is not enough memory, change the soft/strong link of in-memory storages to a weak link. This will allow you to quickly free up memory from unused in-memory storage.
- When integrating a dynamic pro feature, you can designate all objects as weak, which will allow you to smoothly replace them with pro objects
- Protect objects from being deleted for a while. This may be necessary when re-creating the object holder.
Changing the cache works until it is explicitly redefined to the default one, or until the first destruction of each object in the DI cache.
@Component
public interface PlanetsComponent {
@SunScope
@BindInstance
Sun sun(Sun sun);
@SunScope
@SwitchCache(cache = SwitchCache.CacheType.Strong, timeMillis = 100)
void protectSun();
}When certain events occur in the application, it is necessary to temporarily protect objects in the cache from being deleted. For example, during any re-creation of the screen, reconfiguration of the View, where the main holder is re-created, and it is necessary to protect its objects during this re-creation.
Purge protection is available for inject class variables. If the object for which the inject was performed is re-created, then you can temporarily save its objects while it is being re-created.
@Component
public interface PlanetsComponent {
void inject(SolarSystem solarSystem);
@ProtectInjected(timeMillis = 30)
void protectInjected(SolarSystem solarSystem);
}Then at the time of re-creation you can save the variables of the Solar System class
public class SolarSystem {
static PlanetsComponent DI = Stone.createComponent(PlanetsComponent.class);
@Inject
Mercury mercury;
void create() {
DI.inject(this);
}
void beforeRecreate() {
DI.protectInjected(this);
}
}After SolarSystem is recreated, its variables will also be available in the current instances.
In classic applications, objects have standard life cycles, which means we can add protectInjected to the standard mechanism for working with life cycles.
So, if we have a standard life cycle event of object destruction, then it can be used as a trigger for caching objects for a while.
Even if the object is not recreated, it will be possible to set the time after which the saved objects will return to their original caching settings and will be cleared according to these settings.
With each injection method, we can supplement the life cycle parameter StoneLifeCycleOwner
@Component
public interface PlanetsComponent {
void inject(SolarSystem solarSystem, StoneLifeCycleOwner lifeCycleOwner);
}By creating your own implementation of StoneLifeCycleOwner you can manage methods for protecting objects from destruction according to your life cycles in the application.
For Android development, the android_lib library provides the functionality for creating StoneLifeCycleOwner based on the android LifecycleOwner. To do this, it is enough to use the method
class SomeFragment extends Fragment {
@Inject
public SomeViewModel viewModel;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DI.inject(AndroidStone.lifeCycleOwner(getLifecycle()));
}
}