feat(ios): fire onDisplayed event when first frame is ready to be displayed (#5344)

* feat: add a 'profiling: lifecycle' to track startup times

* feat: log when displayed event fires

* feat(ios): fire onDisplayed event when first frame is ready to be
displayed
This commit is contained in:
Stanimira Vlaeva
2018-01-29 13:47:35 +02:00
committed by Alexander Vakrilov
parent 5bae124604
commit 1c78e4784c
4 changed files with 92 additions and 14 deletions

View File

@@ -2,6 +2,12 @@
require("globals");
import { Observable, EventData } from "../data/observable";
import {
trace as profilingTrace,
time,
uptime,
level as profilingLevel,
} from "../profiling";
const events = new Observable();
let launched = false;
@@ -11,6 +17,15 @@ function setLaunched() {
}
events.on("launch", setLaunched);
if (profilingLevel() > 0) {
events.on("displayed", () => {
const duration = uptime();
const end = time();
const start = end - duration;
profilingTrace(`Displayed in ${duration.toFixed(2)}ms`, start, end);
});
}
export function hasLaunched(): boolean {
return launched;
}

View File

@@ -20,14 +20,12 @@ import { ios as iosView, View } from "../ui/core/view";
import { Frame, NavigationEntry } from "../ui/frame";
import { ios } from "../ui/utils";
import * as utils from "../utils/utils";
import { profile } from "../profiling";
import { profile, level as profilingLevel, Level } from "../profiling";
class Responder extends UIResponder {
//
}
let displayedOnce = false;
class NotificationObserver extends NSObject {
private _onReceiveCallback: (notification: NSNotification) => void;
@@ -46,6 +44,24 @@ class NotificationObserver extends NSObject {
};
}
let displayedOnce = false;
let displayedLinkTarget;
let displayedLink;
class CADisplayLinkTarget extends NSObject {
onDisplayed(link: CADisplayLink) {
link.invalidate();
const ios = utils.ios.getter(UIApplication, UIApplication.sharedApplication);
const object = iosApp;
displayedOnce = true;
notify(<ApplicationEventData>{ eventName: displayedEvent, object, ios });
displayedLinkTarget = null;
displayedLink = null;
}
public static ObjCExposedMethods = {
"onDisplayed": { returns: interop.types.void, params: [CADisplayLink] }
}
}
class IOSApplication implements IOSApplicationDefinition {
private _delegate: typeof UIApplicationDelegate;
private _currentOrientation = utils.ios.getter(UIDevice, UIDevice.currentDevice).orientation;
@@ -101,6 +117,13 @@ class IOSApplication implements IOSApplicationDefinition {
@profile
private didFinishLaunchingWithOptions(notification: NSNotification) {
if (!displayedOnce && profilingLevel() >= Level.lifecycle) {
displayedLinkTarget = CADisplayLinkTarget.new();
displayedLink = CADisplayLink.displayLinkWithTargetSelector(displayedLinkTarget, "onDisplayed");
displayedLink.addToRunLoopForMode(NSRunLoop.mainRunLoop, NSDefaultRunLoopMode);
displayedLink.addToRunLoopForMode(NSRunLoop.mainRunLoop, UITrackingRunLoopMode);
}
this._window = UIWindow.alloc().initWithFrame(utils.ios.getter(UIScreen, UIScreen.mainScreen).bounds);
// TODO: Expose Window module so that it can we styled from XML & CSS
this._window.backgroundColor = utils.ios.getter(UIColor, UIColor.whiteColor);
@@ -126,11 +149,6 @@ class IOSApplication implements IOSApplicationDefinition {
if (rootView && !rootView.isLoaded) {
rootView.callLoaded();
}
if (!displayedOnce) {
notify(<ApplicationEventData>{ eventName: displayedEvent, object, ios });
displayedOnce = true;
}
}
private didEnterBackground(notification: NSNotification) {