1. 引言

下面我们要讲的这个应用是模拟天气预报应用weather.lzx,在该应用中通过ajax来远程请求数据,进行当前天气预报信息的显示。

2. 需求分析

2.1 weather.lzx主要显示的是每个城市的天气预报信息,我们可以通过左右切换来查看不同城市的天气信息,由于所有城市的天气信息界面都一样,所以该应用中只包含一个主界面就可以了。在该界面中需要包含天气图片、名称、日期、风力天气状况、温度、空气质量、紫外线强度以及48小时和72小时内的天气状况。
2.2 由于天气预报的信息是实时信息,所以在显示当前城市的天气信息时,我们采用ajax技术来进行数据请求。
2.3 每次进行ajax请求数据时,需要有个动画效果来表明当前正在请求过程中。

3. 编码详细讲解。

功能在上面我们已经基本上进行分析了,下面来讲一下具体的代码编写:
1.1 定义图片。
由于在该应用中,需要根据天气状况来显示不同的图片,为了便于代码的可读性,我们定义一个resource.lzx,先通过<resource>来引入图片,然后在视图中使用。如
resource.lzx
<library>
<resource name="space" src="images/1px.gif"/>
<resource name="downico">
    <frame src="images/tv--jiantou.gif"/>
    <frame src="images/tv--jiantou2.gif"/>
</resource>
<resource name="bgimage" src="images/tqyb-background.gif"/>	
<resource name="logoimg" >	
	<frame src="images/01.gif"/><!--暴雨-->
	<frame src="images/01.gif"/><!--大雨-->
	<frame src="images/01.gif"/><!--中雨-->
	<frame src="images/01.gif"/><!--小雨-->
	<frame src="images/01.gif"/><!--阵雨-->
	<frame src="images/05.gif"/><!--大雪-->
	<frame src="images/06.gif"/><!--中雪-->
	<frame src="images/07.gif"/><!--小雪-->
	<frame src="images/08.gif"/><!--冰雹-->
	<frame src="images/1px.gif"/><!--冻雨-->
	<frame src="images/10.gif"/><!--雨夹雪-->
	<frame src="images/1px.gif"/><!--霜冻-->
	<frame src="images/1px.gif"/><!--大风-->
	<frame src="images/1px.gif"/><!--沙尘暴-->
	<frame src="images/03.gif"/><!--阴-->
	<frame src="images/1px.gif"/><!--雾-->
    <frame src="images/14.gif"/><!--多云-->
    <frame src="images/17.gif"/><!--晴-->
    <frame src="images/1px.gif"/><!--晴-->
</resource>
</library>
1.2 Ajax请求数据 同样为了代码的可读性,我们单独建立一个js.lzx,把ajax请求的相关js代码写在该lzx文件中。需要先创建一个js.lzx。
因为是模拟城市的天气信息,所以我们先定义一个数组,表示请求该数组内城市的天气信息如:
var cities=["长春","海口","北京","上海","深圳","乌鲁木齐","南昌","香港","澳门","武汉"];
在使用ajax时,需要先创建一个XMLHttpRequest()对象,如:
var ajax=new XMLHttpRequest();
请求某个城市的天气信息时,我们定义了一个request()函数来进行请求:
function request(cityname){
    top.show(true);
    city.setText(cityname);
	ajax.abort();
	ajax.onreadystatechange=getResponse;
	ajax.open("POST","http://222.128.6.118/elooapp/*/weather/Weather?clientflag=abce&action=get3DayForecastByCity&city="+cityname,true);
	//ajax.open("POST","http://localhost/070903/stock1.xml",true)
	ajax.send(null);	
}
在该函数中,参数为当前城市的名称,top.show(true)是使连接状态的界面进行显示,city.setText(cityname)在界面上显示当前请求城市的名称,ajax.abort()是中断之前的ajax请求,因为在左右切换不同城市的天气信息时,可能按键太快,在上次请求信息还没返回前,又进行了新的一次请求。ajax.onreadystatechange=getResponse;每个ajax状态改变时,都会触发这个事件处理器,getResponse为一个函数名。Ajax.open("POST",url)url为请求的url路径,通过ajax.send()方法把请求发送到指定的目标资源,参数为null就可以了。 请求过程中的图片如图:

当ajax状态改变时,都会触发事件处理器,调用getResponse()函数,ajax.readyState ==4时,表示请求完成,ajax.status==200时,表示请求成功。如:
function getResponse(){
	if(ajax.readyState==4){
		if(ajax.status==200){
			parseXML(ajax.responseXML);
		}
        top.show(false);
	}
}
当请求完成时,我们把连接状态设置成false,为不可见。请求成功时,调用parseXML函数来解析返回的数据。
function parseXML(doc){
	var node=doc.getElementsByTagName("list");
	if(node.length<1) {
		myDebug("返回数据结果错误!");
		return;
	}
	else node=node.item(0);
	var record=[];
	var len=node.childNodes.length;
	var tmp;
	var t;
	for(var i=0;i<len;i++){
		if(node.childNodes.item(i).nodeType==1){
			t=record.length;
			record[t]={};
			tmp=node.childNodes.item(i).childNodes;
			for(var j=0;j<tmp.length;j++){
				var tnode=tmp.item(j);
				if(tnode.nodeType==1) record[t][tnode.nodeName]=tnode.firstChild.data;				
			}
		}
	}
	change(record[0]["icon"],record[0]["condition"],record[0]["low"]+"~"+record[0]["high"],record[0]["windspeed"],record[0]["airquality"],record[0]["ultraviolet"],record[1]["icon"],record[1]["low"]+"~"+record[1]["high"],record[1]["windspeed"],record[2]["icon"],record[2]["low"]+"~"+record[2]["high"],record[2]["windspeed"]);	
}
function change(tl,weatherv,imv,windv,airv,lightv,tlogov,timv,twindv,atlogov,atimv,atwindv){
	var sArr=["todayLogo","weather","im","wind","air","light","tlogo","tim","twind","atlogo",
    "atim","atwind"];
    for(var i=0;i<sArr.length;i++){
        if(i==0||i==6||i==9){
            var number=arguments[i]=="-1"?19:(parseInt(arguments[i])+1)
            window[sArr[i]].setResourceNumber(number);
        }else{
            window[sArr[i]].setText(typeof(arguments[i])=="undefined"?" ":""+arguments[i]);
        }
    }
}
这段代码是解析返回的数据,并把返回的数据作为参数传给change()函数,change()函数的功能主要是把得到的数据显示到界面上。如图:

1.3 初始化界面(index.lzx)
做完上面的工作以后,来初始化信息界面。

如:
<?xml version="1.0" encoding="utf-8" ?>
<canvas width="240" height="320" debug="false"  fontsize="16" font="宋体">
<include href="js.lzx"/>
<include href="resource.lzx"/>
<attribute name="index" type="number" value="0"/>
<view id="bg"  width="240" height="320" resource="bgimage">
    <text fontsize="22"  fgcolor="#FFFFFF" width="100" x="100" y="20" id="apptitle" height="30">天气预报</text>	
    <view x="6" y="18" width="55" height="70" resource="images/app.gif" id="logo" />      
    <text  id="city" x="70" y="61" text=" " width="120"/>	
    <view x="150" y="61">
        <text name="date" align="left" width="120"/>		
        <handler name="oninit">
            var d=new Date();
            this.date.setText(d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate());
        </handler>
    </view>
    <view id="main" fontsize="16" y="60">            
        <view id="todayLogo" x="5" y="35" height="60" width="60" resource="logoimg" stretches="both"/>
        <view   x="70" y="25" height="60"  fontsize="18" >
        <simplelayout axis="y" spacing="5"/>                
            <text  id="weather" text="多云" width="100"/>
            <text  id="im"  text="30" width="100"/>              
        </view>
        
        <view  x="70"  y="75" fontsize="16">
             <simplelayout axis="y" spacing="5"/>                    
            <view height="20">
                <simplelayout axis="x" spacing="1"/>
                <text text="风力:"/>
                <text id="wind" width="100" />
            </view>
            <view  height="20">
                 <simplelayout axis="x" spacing="1"/>
                <text text="空气质量:"/>
                <text id="air"  width="95"/>
            </view>

            <view  height="20"> 
                <simplelayout axis="x" spacing="1"/>
                <text text="紫外线强度:" resize="true"/>
                <text id="light"  width="95" />
            </view>                
        </view>
        <drawview y="150" x="5">
            <handler name="oninit">
            <![CDATA[                
                for(var i=0;i< 230;i+=4 ){
                    this.moveTo(i,0);
                    this.lineTo(i+2,0);
                }
                this.strokeStyle = 0x66ee99;
                this.stroke();
            ]]>
            </handler>
        </drawview>
        
      

        <view name="future" x="5" y="160"  height="60"  fontsize="15"  >      
            <simplelayout axis="y" spacing="5" inset="5"/>
            <view name="tom">
            <simplelayout axis="x" spacing="2"/>
                <text>48小时</text>
                <view id="tlogo"  y="-4" resource="logoimg" width="28" height="28" stretches="both" /> 
                <view >
                    <simplelayout axis="x" spacing="1"/>
                    <text id="tim" width="60"/>
                    <text id="twind" width="95" />
                </view>
            </view>
            <view name="afttom">
                <simplelayout axis="x" spacing="2"/>
                <text>72小时</text>
                <view id="atlogo" resource="logoimg"  y="-4" width="28" height="28" stretches="both" />
                <view>
                    <simplelayout axis="x" spacing="1"/>
                    <text id="atim" width="60"/>                    
                    <text id="atwind"  width="95"/>
                </view>
            </view>       
        </view>
    </view>

    <view id="top" y="135" x="3" visible="false">
        <drawview>
            <handler name="oninit">
                this.strokeStyle=0x9AFF9A;
                this.fillStyle=0xBCEE68;
                this.lineWidth=1;
                this.rect(0,0,232,70);
                this.fill();
                this.stroke();				
            </handler>
        </drawview>		
        <view  x="30" y="20" width="34" height="34" resource="downico" name="flash" />
        <text fontsize="16" fgcolor="green" y="25" x="90" id="downt">连接中...</text>	
    <method name="show" args="flag">
        if(flag){
            this.number=false;
            this.flashTimer();
        }else{
            clearTimeout(this.timer);
            this.timer=null;
        }
        this.setVisible(flag);
    </method>
    <method name="flashTimer">
        clearTimeout(this.timer);
        this.timer=null;
        this.number=!this.number;
        alert("sjftest "+this.number)
        this.flash.setResourceNumber(this.number?1:2);
        this.timer=setTimeout("top.flashTimer()",300);
    </method>
    </view>
    <text x="161" y="293" fgcolor="white" text="退出" height="20"/>
    <handler name="oninit">
         LzFocus.setFocus(canvas);
         canvas.move(0);
    </handler>
</view>
<method name="move" args="p">
<![CDATA[
    this.index+=p;
    if(this.index< 0){
        this.index=cities.length-1;
    }else if(this.index>cities.length-1){
        this.index=0;
    }
    request(cities[this.index]);
]]>
</method>
<handler name="onkeydown" args="key">
<![CDATA[
   switch(key)
   {		
		case 37: //left			
		case 0x100e:
			this.move(-1);
            break;
        case 39: //right
		case 0x100f:
			this.move(1);
            break;
   }
 ]]>
</handler>
</canvas>
在index.lzx文件中,我们需要通过<include>来分别包含之前定义的js.lzx和resource.lzx,如<include href=”js.lzx”>。id为main的视图主要显示的是天气情况,id为top的视图显示的是连接状态的界面,在该界面中的动画效果是通过两张图片进行切换达到的效果。通过id为bg视图下的oninit事件来触发cities数组中第一个城市的天气信息。