Back

【年度最干干货】: 明星框架:把app代码写在远程服务器上。

发布时间: 2016-01-23 09:07:00

认识明星是我2015年做的最有价值的事,之一  ^_^    。

而明星框架,则是我2015年遇到的最牛逼框架,没有之一。

原理:

把app的代码写到服务器端,然后在app端访问远程界面。 把代码缓存到本地。 使用  eval () 来调用。

这个框架能够实现,在技术上有几种依托:

1. 代码不需要编译。  

2. 支持eval 这样的方法 

好处是:  

1. 不需要编译的等待时间。 这边写了那边立马看到

2. 可以随时随地修改app上的代码。

前景: 

这个框架绝对是一种变革

我们把Titanium 看成是 nginx,  则android 就是linux.   我们在linux上写html是不需要编译的, 同理,我写mobile app,骨架部分需要编译, 肌肉部分是不需要的。

过程:

假设你的代码,在titanium上是静态代码:

app.js:
nearby_window = requeir('/lib/nearby_houses.js');

window = Ti.UI.createWindow({
    title: '本地的工地'
})
label = Ti.UI.createLabel({
    text: '这里的内容是本地的,将来要放到远程上'
})
window.add(label)
window.open()

那么,我们要做的是:

1. 先把这个window 在app.js中 抽取出来,成为一个 js module:

app目录下的 /Resources/lib/nearby_houses.js:

Wrapper  = function(){
    window = Ti.UI.createWindow({  
        title: '本地的工地'
    })
    label = Ti.UI.createLabel({
        text: '这里的内容是本地的,将来要放到远程上'
    })
    window.add(label)
    return window;
}

module.exports = Wrapper;

2. 在 Resources/app.js 中,使用 require 来调用这个module:

wrapper = require('lib/nearby_houses.js');
wrapper.open()

运行,没问题~

3. 开始分解  nearby_houses.js, 把它的内容从远程调用:

Wrapper = ->
    Ti.include '/lib/public.js'

    window = Ti.UI.createWindow
        title: '附近的工地'

    setup_window = ->

        http_call
            url: Ti.App.householder_code_url + "/householder_code/nearby_houses.js"
            cache: true
            success: (e) ->
                console.info "== got code successfully"
                some_window = eval(e.responseText)
                some_window(window)

            // 下面部分的代码,是当网络不好时,生成一个消息提示,并且给个按钮,让用户重新下载代码。
            error: () ->
                window.add Ti.UI.createLabel
                    top: __l(100)
                    text: '哎呀,网络连接似乎有点问题!'
                    textAlign: 'center'
                    font: fontSize: __l(18)
                    color: '#333'

                button = Ti.UI.createButton
                    title: "重试"
                    top: __l(150)
                    width: __l(80)
                    font:
                        fontSize: __l(18)
                button.addEventListener "click", (e) ->
                    setup_window()
                window.add(button)

    setup_window()
    window

module.exports = Wrapper

这个 http_call 的方法看起来这样:( 放到 Resources/lib/public.js 中) 

http_call = (options) ->
    if options.cache
        if Ti.App.deployType == "production"
            record = require("/lib/db").db.select_with_check(options.url, 0)
            unless record.blank
                if options.success
                    options.success({ responseText: record.json})

    xhr = Ti.Network.createHTTPClient()
    xhr.timeout = Ti.App.timeout
    xhr.onerror = ->
        if options.error then options.error this else show_timeout_dlg xhr,url
    xhr.onload = ->
        options.success this if options.success
    url = options.url
    if options.url.indexOf(Ti.App.householder_host_url) == 0
        append = "osname="+Ti.App.osname+"&osversion="+Ti.App.osversion+"&appversion="+Ti.App.version+"&manufacturer="+Ti.App.manufacturer+"&model="+Ti.App.model+"&memory="+Ti.Platform.availableMemory
        url += if options.url.indexOf("?") > 0 then "&" + append else "?" + append
    xhr.open options.method || 'GET', url 
    if options.args then xhr.send options.args else xhr.send()

对于 lib/db.coffee :

Bizsim = Bizsim or {}
Bizsim.db = {}

Bizsim.db.select_with_check = (json_type, id) ->
  record = Bizsim.db.select_one_json(json_type, id)
  now = new Date
  #数据3天过期
  if Titanium.Network.online and !record.blank and now.getTime() - (record.created_at) > 1000 * 3600 * 24 * 3
    Bizsim.db.delete_one_json json_type, id
    return { blank: true }
  record
Bizsim.db.delete_one_json = (json_type, id) ->
  Ti.App.db.execute 'delete from jsons where json_type=? and id=?', json_type, id
  return
module.exports = Bizsim

同时,你要有个远程服务器,在远程服务器的 /code/nearby_houses.js 中,要返回这个内容:

NearbyHousesWindow = function(window) {
  Ti.include('/lib/public.js');
  label = Ti.UI.createLabel({
    text: '这个Label被放到了远程服务器上'
  })
  window.add(label);
  return window;
};

module.exports = NearbyHousesWindow;

现在,你要修改window的代码的话,完全不需要编译重启app,  直接在远程修改就完事儿了。

几点注意:

1. 一些module , 不但文件需要放到本地, 代码运行最好也在本地,否则会出现 有时加载不了的情况。 深层原因疑似 网络加载有延迟。 放到本地的话就没有了。 

2. 一些方法,需要提前放到一个 匿名js中运行一下。 例如: 

$ cat Resources/anon.js 
/*
 * 这个文件,系统是不会调用的。
 * 它存在的目的,是为了骗过编译器,(先调用一些API, createTextArea, createOptionDialog)
 * 让编译到实体机时,系统不会出错。
 * Anon 的意思是 Anonymouse
 * */
function AnonWindow(title) {
	var t = Ti.UI.createTextArea({
		hintText: "反馈内容"
	});

	var optionsDialogOpts = {
		title: "选择您想进行的操作",
		options : ["1", "2"],
		cancel : 1
	};

	Titanium.UI.createOptionDialog(optionsDialogOpts);

	Ti.Filesystem.applicationCacheDirectory;

	Titanium.UI.iPhone.TableViewStyle.GROUPED,
	Ti.Geolocation.preferredProvider = "gps";
}

module.exports = AnonWindow;

Back