目前一段时间一直做移动终端开发,使用框架为Sencha Touch,Sencha Touch是基于Html5和Ext的,所以在性能上存在很大的问题,尤其是打开程序的时候需要加载很多模块的javascript类,严重影响了程序进入时的速度,随着模块的增多,速度越来越慢。能优化的已经都优化了,比如把各个模块的model,view,store都放到每个模块的Controller里面单独引入,但是每个模块的Controller是必须要在程序初始化的时候加载的,否则进入模块的时候就会报类找不到异常,目前的代码如下:
controllers : [
"mobile.common.phone.BottomTabPhoneController",
"mobile.common.tablet.BottomTabTabletController",
"mobile.common.SlideViewController",
"mobile.common.organize.OrganizeController",
"mobile.cyyw.CyywController",
"mobile.user.UserController",
"mobile.business.AllBusinessController",
"mobile.qyyh.QyyhController",
"mobile.home.HomePageController",
"mobile.group.GroupController",
"mobile.news.NewsController",
"mobile.txl.TxlController",
‘mobile.blog.BlogController‘,
"mobile.tdxx.TdxxController",
"mobile.fyxx.FyxxController",
"mobile.qyml.QymlController",
"mobile.yzcxm.YzcxmController",
"mobile.jjyxbg.JjyxbgController",
"mobile.gzlc.GzlcController",
"mobile.clzzjk.ClzzjkController",
"mobile.pljk.PljkController",
"mobile.zcjk.ZcjkController",
"mobile.sjpc.SjpcController",
"mobile.ptcb.PtcbController",
"mobile.ytbcb.YtbcbController",
"mobile.file.FileController",
"mobile.rwap.RwapController",
"mobile.syrw.SyrwController",
"mobile.bdss.BdssController",
"mobile.fwjk.FwjkController",
"mobile.wdrw.WdrwController",
],
?这是我的全部模块的Controller,每个Controller里面又引入了该模块的model,view和store,进入程序时候速度慢就是这些Controller影响的,怎样才能在程序初始化的时候只加载必要的Controller而把其它不必要的模块延迟加载呢?查阅官方api并没有这方面的说明,但是问题必须要解决!后来考虑到Sencha Touch在初始化的时候是要加载所有Controller的,那能不能把Sencha Touch官方的代码拷贝出来用于延迟加载单独的Controller呢?抱着试试看的心理我在官方api中搜索有关Controller的代码,发现在Application.js中有一个loadControllerDependencies方法,代码如下:
loadControllerDependencies: function() {
this.instantiateControllers();
var controllers = this.getControllerInstances(),
classes = [],
stores = [],
i, controller, controllerStores, name;
for (name in controllers) {
controller = controllers[name];
controllerStores = controller.getStores();
stores = stores.concat(controllerStores);
classes = classes.concat(controller.getModels().concat(controller.getViews()).concat(controllerStores));
}
this.setStores(this.getStores().concat(stores));
Ext.require(classes, this.onDependenciesLoaded, this);
},
?其中instantiateControllers方法代码如下:
/**
* @private
* Called once all of our controllers have been loaded
*/
instantiateControllers: function() {
var controllerNames = this.getControllers(),
instances = {},
length = controllerNames.length,
name, i;
for (i = 0; i < length; i++) {
name = controllerNames[i];
instances[name] = Ext.create(name, {
application: this
});
}
return this.setControllerInstances(instances);
},
?由代码可以看出,instantiateControllers方法就是实例化Controller本身的方法,而loadControllerDependencies方法还包含了初始化Controller中model,view和store的代码,最后一行代码还包含了一个回调函数onDependenciesLoaded,代码如下:
/**
* @private
* Callback that is invoked when all of the Application, Controller and Profile dependencies have been loaded.
* Launches the controllers, then the profile and application.
*/
onDependenciesLoaded: function() {
var me = this,
profile = this.getCurrentProfile(),
launcher = this.getLaunch(),
controllers, name;
this.instantiateStores();
//<deprecated product=touch since=2.0>
Ext.app.Application.appInstance = this;
if (Ext.Router) {
Ext.Router.setAppInstance(this);
}
//</deprecated>
controllers = this.getControllerInstances();
for (name in controllers) {
controllers[name].init(this);
}
if (profile) {
profile.launch();
}
launcher.call(me);
for (name in controllers) {
//<debug warn>
if (controllers[name] && !(controllers[name] instanceof Ext.app.Controller)) {
Ext.Logger.warn("The controller ‘" + name + "‘ doesn‘t have a launch method. Are you sure it extends from Ext.app.Controller?");
} else {
//</debug>
controllers[name].launch(this);
//<debug warn>
}
//</debug>
}
me.redirectTo(window.location.hash.substr(1));
}
?经测试,其中需要用到的代码只有this.instantiateStores();这一行,功能是初始化Controller中的Store。
找到了关键的代码,下一步要做的是把代码提出来为我作用,由于我需要在进入某个模块的时候再初始化这个模块的Controller,也就是每次只初始化一个Controller,所以里面的一些代码需要修改合并一下,修改合并后的代码如下:
//controllerName是Controller的全限定名,例如:"mobile.bdss.BdssController",mobile.app是当前Ext.app.Application的实例
if (Ext.isEmpty(mobile.app.getController(controllerName))) {
//获得已经实例化过的Controller
var instances = mobile.app.getControllerInstances(),
//实例化当前模块的Controller
controller = Ext.create(controllerName, {
application: mobile.app
});
//把当前模块的Controller加到实例数组中
instances[controllerName]=controller;
//把Controller实例数组还给Ext.app.Application
mobile.app.setControllerInstances(instances);
//把当前Controller中的Stroe赋值给Ext.app.Application
mobile.app.setStores(controller.getStores());
var classes=[];
classes = classes.concat(controller.getModels().concat(controller.getViews()).concat(controller.getStores()));//获得所有类
Ext.require(classes, function(){
mobile.app.instantiateStores();
}, mobile.app);
}
? 这样,在每次进入模块时都执行这段代码,如果没有实例化Controller就实例化,这样我就可以把开头那些不需要进入程序时就加载的Controller去掉,只保留必须的Controller,大大提高程序启动时的时间。
原文:http://14135303.iteye.com/blog/2158117