Skip to content

Commit 3a447b6

Browse files
Added @Profile on several key methods in the Android lifecycle, refactored by extracting into methods a little (NativeScript#4685)
1 parent 7b36461 commit 3a447b6

File tree

8 files changed

+203
-139
lines changed

8 files changed

+203
-139
lines changed

tns-core-modules/application/application.android.ts

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -180,34 +180,45 @@ global.__onLiveSync = function () {
180180
};
181181

182182
function initLifecycleCallbacks() {
183-
// TODO: Verify whether the logic for triggerring application-wide events based on Activity callbacks is working properly
183+
const setThemeOnLaunch = profile("setThemeOnLaunch", (activity: android.app.Activity) => {
184+
// Set app theme after launch screen was used during startup
185+
const activityInfo = activity.getPackageManager().getActivityInfo(activity.getComponentName(), android.content.pm.PackageManager.GET_META_DATA);
186+
if (activityInfo.metaData) {
187+
const setThemeOnLaunch = activityInfo.metaData.getInt("SET_THEME_ON_LAUNCH", -1);
188+
if (setThemeOnLaunch !== -1) {
189+
activity.setTheme(setThemeOnLaunch);
190+
}
191+
}
192+
});
193+
194+
const notifyActivityCreated = profile("notifyActivityCreated", function(activity: android.app.Activity, savedInstanceState: android.os.Bundle) {
195+
androidApp.notify(<AndroidActivityBundleEventData>{ eventName: ActivityCreated, object: androidApp, activity, bundle: savedInstanceState });
196+
});
197+
198+
const subscribeForGlobalLayout = profile("subscribeForGlobalLayout", function(activity: android.app.Activity) {
199+
const rootView = activity.getWindow().getDecorView().getRootView();
200+
let onGlobalLayoutListener = new android.view.ViewTreeObserver.OnGlobalLayoutListener({
201+
onGlobalLayout() {
202+
notify({ eventName: displayedEvent, object: androidApp, activity });
203+
let viewTreeObserver = rootView.getViewTreeObserver();
204+
viewTreeObserver.removeOnGlobalLayoutListener(onGlobalLayoutListener);
205+
}
206+
});
207+
rootView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
208+
});
209+
184210
const lifecycleCallbacks = new android.app.Application.ActivityLifecycleCallbacks({
185211
onActivityCreated: profile("onActivityCreated", function (activity: android.app.Activity, savedInstanceState: android.os.Bundle) {
186-
// Set app theme after launch screen was used during startup
187-
const activityInfo = activity.getPackageManager().getActivityInfo(activity.getComponentName(), android.content.pm.PackageManager.GET_META_DATA);
188-
if (activityInfo.metaData) {
189-
const setThemeOnLaunch = activityInfo.metaData.getInt("SET_THEME_ON_LAUNCH", -1);
190-
if (setThemeOnLaunch !== -1) {
191-
activity.setTheme(setThemeOnLaunch);
192-
}
193-
}
212+
setThemeOnLaunch(activity);
194213

195214
if (!androidApp.startActivity) {
196215
androidApp.startActivity = activity;
197216
}
198217

199-
androidApp.notify(<AndroidActivityBundleEventData>{ eventName: ActivityCreated, object: androidApp, activity, bundle: savedInstanceState });
218+
notifyActivityCreated(activity, savedInstanceState);
200219

201220
if (hasListeners(displayedEvent)) {
202-
const rootView = activity.getWindow().getDecorView().getRootView();
203-
let onGlobalLayoutListener = new android.view.ViewTreeObserver.OnGlobalLayoutListener({
204-
onGlobalLayout() {
205-
notify({ eventName: displayedEvent, object: androidApp, activity });
206-
let viewTreeObserver = rootView.getViewTreeObserver();
207-
viewTreeObserver.removeOnGlobalLayoutListener(onGlobalLayoutListener);
208-
}
209-
});
210-
rootView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
221+
subscribeForGlobalLayout(activity);
211222
}
212223
}),
213224

tns-core-modules/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@
3939
"snapshot": {
4040
"android": {
4141
"tns-java-classes": {
42-
"modules": ["ui/frame/activity", "ui/frame/fragment"]
42+
"modules": [
43+
"ui/frame/activity",
44+
"ui/frame/fragment"
45+
]
4346
}
4447
}
4548
}

tns-core-modules/ui/builder/builder.ts

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { isString, isDefined } from "../../utils/types";
1010
import { ComponentModule, setPropertyValue, getComponentModule } from "./component-builder";
1111
import { platformNames, device } from "../../platform";
1212
import { resolveFileName } from "../../file-system/file-name-resolver";
13+
import { profile } from "tns-core-modules/profiling";
1314
import * as traceModule from "../../trace";
1415

1516
const ios = platformNames.ios.toLowerCase();
@@ -445,28 +446,28 @@ namespace xml2ui {
445446
this._state = TemplateParser.State.FINISHED;
446447

447448
if (this._setTemplateProperty && this._templateProperty.name in this._templateProperty.parent.component) {
448-
let template = this._build();
449+
let template = this.buildTemplate();
449450
this._templateProperty.parent.component[this._templateProperty.name] = template;
450451
}
451452
}
452453
}
453454

454-
public _build(): Template {
455+
public buildTemplate(): Template {
455456
var context = this._context;
456457
var errorFormat = this._templateProperty.errorFormat;
457458
var sourceTracker = this._templateProperty.sourceTracker;
458-
var template: Template = () => {
459+
var template: Template = profile("Template()", () => {
459460
var start: xml2ui.XmlArgsReplay;
460461
var ui: xml2ui.ComponentParser;
461462

462463
(start = new xml2ui.XmlArgsReplay(this._recordedXmlStream, errorFormat))
463-
// No platform filter, it has been filtered allready
464+
// No platform filter, it has been filtered already
464465
.pipe(new XmlStateParser(ui = new ComponentParser(context, errorFormat, sourceTracker)));
465466

466467
start.replay();
467468

468469
return ui.rootComponentModule.component;
469-
}
470+
});
470471
return template;
471472
}
472473
}
@@ -492,7 +493,7 @@ namespace xml2ui {
492493
for (let i = 0; i < this._childParsers.length; i++) {
493494
templates.push({
494495
key: this._childParsers[i]["key"],
495-
createView: this._childParsers[i]._build()
496+
createView: this._childParsers[i].buildTemplate()
496497
});
497498
}
498499
this.templateProperty.parent.component[this.templateProperty.name] = templates;
@@ -535,6 +536,22 @@ namespace xml2ui {
535536
this.sourceTracker = sourceTracker;
536537
}
537538

539+
@profile
540+
private buildComponent(args: xml.ParserEvent): ComponentModule {
541+
if (args.prefix && args.namespace) {
542+
// Custom components
543+
return loadCustomComponent(args.namespace, args.elementName, args.attributes, this.context, this.currentRootView);
544+
} else {
545+
// Default components
546+
let namespace = args.namespace;
547+
if (defaultNameSpaceMatcher.test(namespace || '')) {
548+
//Ignore the default ...tns.xsd namespace URL
549+
namespace = undefined;
550+
}
551+
return getComponentModule(args.elementName, namespace, args.attributes, this.context, this.moduleNamePath);
552+
}
553+
}
554+
538555
public parse(args: xml.ParserEvent): XmlStateConsumer {
539556

540557
// Get the current parent.
@@ -579,20 +596,7 @@ namespace xml2ui {
579596

580597
} else {
581598

582-
var componentModule: ComponentModule;
583-
584-
if (args.prefix && args.namespace) {
585-
// Custom components
586-
componentModule = loadCustomComponent(args.namespace, args.elementName, args.attributes, this.context, this.currentRootView);
587-
} else {
588-
// Default components
589-
let namespace = args.namespace;
590-
if (defaultNameSpaceMatcher.test(namespace || '')) {
591-
//Ignore the default ...tns.xsd namespace URL
592-
namespace = undefined;
593-
}
594-
componentModule = getComponentModule(args.elementName, namespace, args.attributes, this.context, this.moduleNamePath);
595-
}
599+
var componentModule = this.buildComponent(args);
596600

597601
if (componentModule) {
598602
this.sourceTracker(componentModule.component, args.position);

tns-core-modules/ui/builder/component-builder/component-builder.ts

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { isEventOrGesture } from "../../core/bindable";
77
import { File, path, knownFolders } from "../../../file-system";
88
import { getBindingOptions, bindingConstants } from "../binding-builder";
99
import { resolveFileName } from "../../../file-system/file-name-resolver";
10+
import { profile } from "tns-core-modules/profiling";
1011
import * as debugModule from "../../../utils/debug";
1112
import * as platform from "../../../platform";
1213

@@ -24,14 +25,9 @@ const CODEFILE = "codeFile";
2425
const CSSFILE = "cssFile";
2526
const IMPORT = "import";
2627

27-
export function getComponentModule(elementName: string, namespace: string, attributes: Object, exports: Object, moduleNamePath?: string): ComponentModule {
28+
const createComponentInstance = profile("createComponentInstance", (elementName: string, namespace: string): { instance: View, instanceModule: Object } => {
2829
var instance: View;
2930
var instanceModule: Object;
30-
var componentModule: ComponentModule;
31-
32-
// Support lower-case-dashed component declaration in the XML (https://github.com/NativeScript/NativeScript/issues/309).
33-
elementName = elementName.split("-").map(s => { return s[0].toUpperCase() + s.substring(1) }).join("");
34-
3531
// Get module id.
3632
var moduleId = MODULES[elementName] || UI_PATH +
3733
(elementName.toLowerCase().indexOf("layout") !== -1 ? "layouts/" : "") +
@@ -70,7 +66,10 @@ export function getComponentModule(elementName: string, namespace: string, attri
7066
throw new debug.ScopeError(ex, "Module '" + moduleId + "' not found for element '" + (namespace ? namespace + ":" : "") + elementName + "'.");
7167
}
7268

73-
let cssApplied = false;
69+
return { instance, instanceModule };
70+
});
71+
72+
const getComponentModuleExports = profile("getComponentModuleExports", (instance: View, moduleExports: Object, attributes: Object): Object => {
7473
if (attributes) {
7574
if (attributes[IMPORT]) {
7675
let importPath = attributes[IMPORT].trim();
@@ -79,39 +78,43 @@ export function getComponentModule(elementName: string, namespace: string, attri
7978
importPath = path.join(knownFolders.currentApp().path, importPath.replace("~/", ""));
8079
}
8180

82-
exports = global.loadModule(importPath);
83-
(<any>instance).exports = exports;
81+
moduleExports = global.loadModule(importPath);
82+
(<any>instance).exports = moduleExports;
8483
}
8584

86-
// if (instance instanceof Page) {
87-
if (attributes[CODEFILE]) {
88-
let codeFilePath = attributes[CODEFILE].trim();
89-
if (codeFilePath.indexOf("~/") === 0) {
90-
codeFilePath = path.join(knownFolders.currentApp().path, codeFilePath.replace("~/", ""));
91-
}
85+
if (attributes[CODEFILE]) {
86+
let codeFilePath = attributes[CODEFILE].trim();
87+
if (codeFilePath.indexOf("~/") === 0) {
88+
codeFilePath = path.join(knownFolders.currentApp().path, codeFilePath.replace("~/", ""));
89+
}
9290

93-
const codeFilePathWithExt = codeFilePath.indexOf(".js") !== -1 ? codeFilePath : `${codeFilePath}.js`;
94-
if (File.exists(codeFilePathWithExt)) {
95-
exports = global.loadModule(codeFilePath);
96-
(<any>instance).exports = exports;
97-
} else {
98-
throw new Error(`Code file with path "${codeFilePathWithExt}" cannot be found!`);
99-
}
91+
const codeFilePathWithExt = codeFilePath.indexOf(".js") !== -1 ? codeFilePath : `${codeFilePath}.js`;
92+
if (File.exists(codeFilePathWithExt)) {
93+
moduleExports = global.loadModule(codeFilePath);
94+
(<any>instance).exports = moduleExports;
95+
} else {
96+
throw new Error(`Code file with path "${codeFilePathWithExt}" cannot be found!`);
10097
}
98+
}
99+
}
100+
return moduleExports;
101+
});
101102

102-
if (attributes[CSSFILE] && typeof (<any>instance).addCssFile === "function") {
103-
let cssFilePath = attributes[CSSFILE].trim();
104-
if (cssFilePath.indexOf("~/") === 0) {
105-
cssFilePath = path.join(knownFolders.currentApp().path, cssFilePath.replace("~/", ""));
106-
}
107-
if (File.exists(cssFilePath)) {
108-
(<any>instance).addCssFile(cssFilePath);
109-
cssApplied = true;
110-
} else {
111-
throw new Error(`Css file with path "${cssFilePath}" cannot be found!`);
112-
}
103+
const applyComponentCss = profile("applyComponentCss", (instance: View, moduleNamePath: string, attributes: Object) => {
104+
let cssApplied = false;
105+
if (attributes) {
106+
if (attributes[CSSFILE] && typeof (<any>instance).addCssFile === "function") {
107+
let cssFilePath = attributes[CSSFILE].trim();
108+
if (cssFilePath.indexOf("~/") === 0) {
109+
cssFilePath = path.join(knownFolders.currentApp().path, cssFilePath.replace("~/", ""));
110+
}
111+
if (File.exists(cssFilePath)) {
112+
(<any>instance).addCssFile(cssFilePath);
113+
cssApplied = true;
114+
} else {
115+
throw new Error(`Css file with path "${cssFilePath}" cannot be found!`);
113116
}
114-
// }
117+
}
115118
}
116119

117120
if (typeof (<any>instance).addCssFile === "function") {//instance instanceof Page) {
@@ -129,7 +132,9 @@ export function getComponentModule(elementName: string, namespace: string, attri
129132
(<any>instance)._refreshCss();
130133
}
131134
}
135+
});
132136

137+
const applyComponentAttributes = profile("applyComponentAttributes", (instance: View, instanceModule: Object, moduleExports: Object, attributes: Object) => {
133138
if (instance && instanceModule) {
134139
for (let attr in attributes) {
135140

@@ -157,16 +162,28 @@ export function getComponentModule(elementName: string, namespace: string, attri
157162
}
158163

159164
if (subObj !== undefined && subObj !== null) {
160-
setPropertyValue(subObj, instanceModule, exports, subPropName, attrValue);
165+
setPropertyValue(subObj, instanceModule, moduleExports, subPropName, attrValue);
161166
}
162167
} else {
163-
setPropertyValue(instance, instanceModule, exports, attr, attrValue);
168+
setPropertyValue(instance, instanceModule, moduleExports, attr, attrValue);
164169
}
165170
}
171+
}
172+
});
173+
174+
export function getComponentModule(elementName: string, namespace: string, attributes: Object, moduleExports: Object, moduleNamePath?: string): ComponentModule {
175+
// Support lower-case-dashed component declaration in the XML (https://github.com/NativeScript/NativeScript/issues/309).
176+
elementName = elementName.split("-").map(s => { return s[0].toUpperCase() + s.substring(1) }).join("");
166177

178+
const { instance, instanceModule } = createComponentInstance(elementName, namespace);
179+
moduleExports = getComponentModuleExports(instance, moduleExports, attributes);
180+
applyComponentCss(instance, moduleNamePath, attributes);
181+
applyComponentAttributes(instance, instanceModule, moduleExports, attributes);
182+
183+
var componentModule;
184+
if (instance && instanceModule) {
167185
componentModule = { component: instance, exports: instanceModule };
168186
}
169-
170187
return componentModule;
171188
}
172189

0 commit comments

Comments
 (0)