fragment lifecycle when activity stopped - android-activity

When activity is moved to "stopped" state,then what will happen to the life cycle of a "fragment" which is in that activity?

Fragment onStop() method called, when activity is moved to stopped state. For more go through this link & understand fragment and activity states:
https://google-developer-training.gitbooks.io/android-developer-advanced-course-concepts/content/unit-1-expand-the-user-experience/lesson-1-fragments/1-2-c-fragment-lifecycle-and-communications/1-2-c-fragment-lifecycle-and-communications.html

Related

On Android, Where else can a FlutterEngine be displayed except for Activity (and when?)?

In what other cases is the FlutterEngine available but the Android Activity isn't? For example, if I am running a static BroadcastReceiver when the app is not running, there is definitely no activity, but is there a FlutterEngine? I need to know the characteristics of Flutter in the Android lifecycle. I was reading an article (Modern Flutter Plugin Development) by the Flutter team, which mentions
// You cannot access an Activity here because this
// FlutterEngine is not necessarily displayed within an
// Activity. See the ActivityAware interface for more info.
This is partially answered in the ActivityAware documentation, under the onDetachedFromActivity method.
Detachment can occur for a number of reasons.
The app is no longer visible and the Activity instance has been destroyed.
The FlutterEngine that this plugin is connected to has been detached from its FlutterView.
This ActivityAware plugin has been removed from its FlutterEngine.
However, I wish it went into more depth. Here are some things I (don't) understand in depth:
When the activity is destroyed as per the Android activity lifecycle, the activity is gone. The FlutterEngine might still be around, in case a new activity is launched in the future. Perhaps there is still a component running in the Android app, e.g. a Service, and the FlutterEngine does not get destroyed yet? I wonder which cases FlutterEngine does not get destroyed when the activity gets destroyed.
A FlutterView can detach from the engine, and this is probably done if you're adding/ removing Flutter from a native Android app (aka. using add-to-app). You probably don't have to worry about FlutterView detaching from FlutterEngine. In a normal Flutter app, in what cases does FlutterView detach from FlutterEngine?:
This FlutterView will clear its UI and stop forwarding all events to the previously-attached FlutterEngine. This includes touch events, accessibility events, keyboard events, and others.
The relatively easy one: If a plugin unregisters from the FlutterEngine, Flutter cleans up the plugin by calling this method. You don't manually unregister plugins. You'd have to find out when Flutter unregisters plugins on your behalf. When?
To answer my questions after reading the Flutter Android shell code:
I wonder which cases FlutterEngine does not get destroyed when the activity gets destroyed.
When a Fragment or Activity gets detached or destroyed, the Engine might get destroyed. This is the only case where this happens. The Activity/ Fragment being destroyed is configurable by e.g. EXTRA_DESTROY_ENGINE_WITH_ACTIVITY:
#Override
public boolean shouldDestroyEngineWithHost() {
boolean explicitDestructionRequested =
getIntent().getBooleanExtra(EXTRA_DESTROY_ENGINE_WITH_ACTIVITY, false);
if (getCachedEngineId() != null || delegate.isFlutterEngineFromHost()) {
// Only destroy a cached engine if explicitly requested by app developer.
return explicitDestructionRequested;
} else {
// If this Activity created the FlutterEngine, destroy it by default unless
// explicitly requested not to.
return getIntent().getBooleanExtra(EXTRA_DESTROY_ENGINE_WITH_ACTIVITY, true);
}
}
or for fragments:
#Override
public boolean shouldDestroyEngineWithHost() {
boolean explicitDestructionRequested =
getArguments().getBoolean(ARG_DESTROY_ENGINE_WITH_FRAGMENT, false);
if (getCachedEngineId() != null || delegate.isFlutterEngineFromHost()) {
// Only destroy a cached engine if explicitly requested by app developer.
return explicitDestructionRequested;
} else {
// If this Fragment created the FlutterEngine, destroy it by default unless
// explicitly requested not to.
return getArguments().getBoolean(ARG_DESTROY_ENGINE_WITH_FRAGMENT, true);
}
}
Therefore, the user can actually specify this.
If the flutter engine is cached, it won't get destroyed. It doesn't get put into the cache by default, developers have to do this themselves. Therefore, not relevant in a normal flutter app.
If the activity/ fragment creates this FlutterEngine, it gets destroyed. This is the default case in a normal Flutter app.
Both of the above can be disabled by the user if they explicitly set it.
The mechanism to destroy a FlutterEngine, aka. when flutterEngine.destroy(); is called, is done only in onDetach() of the FlutterActivityAndFragmentDelegate. So the question would be: when does the Activity get detached?
In a normal Flutter app, in what cases does FlutterView detach from FlutterEngine?:
When the FlutterView is attempting to attach to a different Flutter engine, it will detach from its current FlutterEngine, if it is attached.
The FlutterView will detach from the Engine when the Activity or Fragment is being detached from the Flutter Engine. Right before the FlutterEngine might get destroyed.
You'd have to find out when Flutter unregisters plugins on your behalf. When?
When the Activity or Fragment detaches from the FlutterEngine, and the FlutterEngine is destroyed, its associated PluginRegistry is destroyed, and when this happens, all the plugins are removed by calling PluginRegistry.removeAll.`
I wonder which cases FlutterEngine does not get destroyed when the activity gets destroyed.
I think it depends on which activity and how you've decided to implement it.
I imagine one scenario is, an instance of FlutterEngine is created by the MainActivity and lives for as long as that activity is around.
If you have more than one Activity then you'd have a choice. Keep a single FlutterEngine instance around in memory and attach/detach the various activities, or destroy the instance and create a new for for each Activity.
I couldn't comment on best practice.
Running multiple Flutters
Though this link raises an interesting scenario.
https://flutter.dev/docs/development/add-to-app/multiple-flutters
FlutterView
Not entirely sure what your question is here. But given https://flutter.dev/docs/development/add-to-app/android/add-flutter-view It appears that you do a lot of manual binding between the activity, view and your Flutter view (binding thats done automatically with the FlutterFragment or FlutterActivity)
As such, when the FlutterView is or is not disaplayed is very much tied to the activity Life cycle in control of that View and the bindings you setup in the first instance.
The link above also states the minimum API's to implement for FlutterView to work properly.
The absolute minimum implementation needed for Flutter to draw anything at all is to:
Call attachToFlutterEngine when the FlutterView is added to a resumed
Activity’s view hierarchy and is visible; and
Call appIsResumed on the FlutterEngine’s lifecycleChannel field when
the Activity hosting the FlutterView is visible.
The reverse detachFromFlutterEngine and other lifecycle methods on the
LifecycleChannel class must also be called to not leak resources when
the FlutterView or Activity is no longer visible.

Where can I found documentation about page lifecycle events?

I am using cdp (https://github.com/mafredri/cdp) in order to use devtools protocol to generate a pdf of a page. But first I need to know when the page is completely loaded. I found that the networkIdle event can help me to know when this occurs. But, I have troubles because the networkIdle event sometimes fired twice. Then I need to know when this one is fired
There are two parts for what you're looking for.
First of all, the reason the event is fired twice. When a new tab (target) is created, the first page it loads is about:blank. You get lifecycle events for this page as well. The second time the load event is fired is the one you're looking for (if you're using Page.lifecycleEvent).
Now, to handle the second matter - there are also other events you can use. The basic one for page loading is Page.loadEventFired, which, as far as I recall, will only be fired for the actual page (but I could be wrong about this one).
Important note: If you're using lifecycle events, they are fired for each frame separately, meaning that the main frame might finish loading before the sub frames are loaded. Page.loadEventFired has a different behavior and waits for all frames to fire their load event.
Here is a good article on the page lifecycle api.
Another possible solution could be:
document.onreadystatechange = function () {
if (document.readyState === 'complete') {
run the screenshot code...
}
}

Ionic- need an event after page is backed

I need an event of page which is backed.
IonWillEnter or ionViewDiEnter events aren't fired when page is backed.
Ionic framework seems to show page simply when a back button is clicked.
Would you like to teach me?
Sorry for my poor English.
Thanks
For your info.. Ionic 2 lifecycle method
ionViewDidLoad - works the same way as ngOnInit, fires once when the view is
initially loaded into the DOM
ionViewWillEnter and ionViewDidEnter - hooks that are available before and after the page becomes active
ionViewWillLeave and ionViewDidLeave - hooks that are available before and after the page leaves the viewport
ionViewWillUnload - is available before the page is removed from the DOM
You should use ionViewWillLeave / ioniViewDidLeave to track the page back/close event
According to https://ionicframework.com/blog/navigating-lifecycle-events/
ionViewWillEnter: It’s fired when entering a page, before it becomes the active one. Use it for tasks you want to do every time you enter in the view (setting event listeners, updating a table, etc.).
ionViewDidEnter: Fired when entering a page, after it becomes the active page. Quite similar to the previous one.
So you can use any of above. I prefer ionViewDidEnter more in this scenario so screen render faster if you call any API.

Finish activity onPause but still be in backstack?

I'm trying to minimize memory usage in my app, and one of the things I'm doing is calling finish() in the onPause method (which I know is not the best way to do things). For the most part, it seems to be working well, but when the user clicks the back button from the next activity, it logically skips over the finished activity and goes back further. Is it possible to have that activity in the back stack and just get recreated if the user presses back?
No. This conclusion comes from the task and backstack documentation as well as the activity documentation and a general understanding of how a stack data structure works.
A stack data strucure only has 2 possible operations push/put, which adds something to the collection, and pop, which removes it. Stacks folow a last in first out model, or LIFO, where by last thing added - in your case an activity - is the first thing removed when pop is called.
Within the android lifecycle activities are generally popped from the stack when the back button is pressed. At that point onDestroy() is called and the activity is removed (you can verify this by overriding the onDestroy() method and logging the results if you want to check). Alternativly you can force onDestroy() to be called by calling finish() as you are. Finishing an activity effectivly does the same thing as pressing back. The activity is destroyed and must be recreated before it can be added to the stack.
For what you're trying to do the stack would have to incorporate some intermediate state in which an activity does not exist but rather something akin to a reference is held that, when moved to the top, would indicate that the corresponding activity should be recreated. Since this is not how the sack works - it only holds activities - that state cannont exist and so the result you are talking about is not possible.
Your Goal is to minimize memory usage,Just make use of activity life cycle, You can do this alternative(if you need)
-Just leave onCreate() method blank.(only do setContentView(layout))
-Override onResume();
-whatever you were doing in onCreate just copy paste to onResume().
-and In onPause(), Recycle your all bitmaps and set them to null(I think you are using Bitmaps thats why you are very cautious about it ). and remove your views.
Now what will happen, when you launch your new activity, onPause() would be called. that will remove your all bitmap and views. and when you come back, onResume() will be call.(onCreate will not be called). and that will again initialize your view and bitmaps.
No, i don't think that is possible. Once you finish the Activity it's gone. You could, however, implement and handle your own stack. On back pressed, you would just start the closed Activity again.

GWT button clicks getting laggy very quickly using Places/Activities in GWT2.1

i'm new to GWT2.1's Places and Activities.
I'm using the same ActivityMapper as example below and getting laggy button clicks after just a few navigations.
The MVP architecture I'm using has the Presenter create listeners and define the View interface, but View objects are singletons.
Is my problem with lag due to all the listeners building up exponentially? Should I change it so that the View creates all the listeners instead? Or should I try unbinding instead?
E.g. in the GWT2.1 example here a new Activity is created every time getActivity(Place) is called.
public Activity getActivity(Place place) {
if (place instanceof HelloPlace)
return new HelloActivity((HelloPlace) place, clientFactory);
else if (place instanceof GoodbyePlace)
return new GoodbyeActivity((GoodbyePlace) place, clientFactory);
return null;
}
The view here adds event handlers to its widgets. It later calls its presenter when appropiate. I don't think that unbindinding the events would free up much memory or speed up the browser's event queue.
I believe you should further investigate if the actual button click is slow, or if it's the creation of Activities happening upon the event, or whatever else.
In the end I changed the MVP architecture to the same as the example here with View defining Activity and ViewImpl containing the UI Handlers. Since the Activities no longer contain handlers and the ViewImpls are singletons the problem goes away.