下载池

由于http下载是异步事件,也就是说下载完成需要由系统调用onWIFI32事件来确定下载完成,这就导致了:

因此我们构建了下载池,把需要下载的任务统一放在下载池中,逐一下载,将并行的任务变成整体的串行任务;详细实现如下:

实现

首先下载池我们构建在appbase这个全局控件中,主要代码如下:

//本代码在appbase控件代码中
//属性:
str dnpool="";    //下载池存储 ,这是一个strlist,一行一个下载url
/*  下载池:    存储在属性:dnpool中 是一个strlist
    url|addr|size|mode   //bin url
    url|x|x|x|           //str url

*/

//方法:
int dnpool_chk(str url,int bs){
    //检测url是否存在
    int i;
    int count;
    str s;
    url=strreplace(url,"|","#SU#"); //转义
    count=strlist_count(bs);
    for (i=0;i<count;i++){
        s=explode_str(strlist_get(bs,i),"|",0);
        if(s==url){
            return i;    
        }
    }
    return -1;
}
void dnpool_add(str url,int addr,int size,int mode){
    //添加一个待下载    
    int bs;
    str s;
    int js;
    bs=strlist_creat(dnpool);
    //根据url查重
    js=dnpool_chk(url,bs);
    if (js==-1){
        if (size==0){
            s=url+"|x|x|x";
        }else{
            s=url+"|"+addr+"|"+size+"|"+mode;
        }
        strlist_add(bs,s);
    }
}
int dnpool_start(){
    //下载 有内容下载返回1 无内容返回0  busy返回2
    int bs;
    str s;
    str url;
    str ss;
    int addr;
    int size;
    int mode;    
    //echo("\r\ndnpool='"+dnpool+"';\r\n");
    if (dnpool=="") return 0;
    if ($dnpool_busy==1) return 2;
    bs=strlist_creat(dnpool);
    s=strlist_get(bs,0);
    url=explode_str(s,"|",0);
    url=strreplace(url,"#SU#","|"); //转义
    if (url=="") return 0;
    ss=explode_str(s,"|",1);
    $dnpool_busy=1;    //busy标志置位
    if (ss=="*"){
        //get str模式
        wifi_httpget(url);
    }
    else{
        //dnbin模式
        addr=explode_num(s,"|",1);
        size=explode_num(s,"|",2);
        mode=explode_num(s,"|",3);
        wifi_httpdnbin(url,addr,size,mode);
    }
    strlist_del(bs,0);
    return 1;
}
void dnpool_run(){
    //dnpool调用入口
    //$dnpool_type  0-无  1-add  2-run  
    //bind dnpool_url  url
    //$dnpool_addr,$dnpool_size,$dnpool_mode
    int r;
    if ($dnpool_type==2){
        r=dnpool_start();
    }
    if ($dnpool_type==1){
        str url;
        url=bind_get("dnpool_url");
        dnpool_add(url,$dnpool_addr,$dnpool_size,$dnpool_mode);
        r=dnpool_start();
    }
    if (r==0)
    {  $dnpool_type=0;
    }
}

//事件:

void onWIFI32(int m){
     int msgnum;
     str s;
     msgnum=wifi_getinfo(2);
     if (m==7){
           //mqtt 协议的处理代码(此处略)
   }
   if (m==4){  //httpdnbin 下载二进制数据完成
           $dnpool_busy=0;    //下载完成
           //---下面代码是执行其他控件注册到onWIFI32上的钩子代码,完成回调
           hook_run("onWIFI32","*","*");   //获取onWIFI32所有的hook项目,并可赋值
        hook_set(wifi_getinfo(5));   //url
        hook_set(wifi_getinfo(19));   //size
    }
    if (m==3)    //httpget
    {    $dnpool_busy=0;    //下载完成
        .....  //对应处理代码,此处略
    }
}

调用

本例中以url为样本,详细介绍调用方法:

 //此代码在urljpg控件代码中

 //属性:
 int st=0;    //状态 =0表示未下载  =1表示已下载

 //方法:
void create()
{     //设定hook钩子,将urljpg.doWIFI这个方法钩在appbase的onWIFI32事件上
    hook_add("onWIFI32","urljpg","doWIFI"); 
}
void show()
{    //在此书写刷新前景的语句
    //automode(bc); or tranmode(n); //选择显示模式,具体讲解请参见语句说明书
    automode(bc);
    if ((url!="")&(st==0)){
        //wifi_httpdnbin(url,0xa0000,256000,1);
        bind_set("dnpool_url",url);
        $dnpool_type=1; 
        $dnpool_addr=0xa0000;
        $dnpool_size=256000;
        $dnpool_mode=1;
        callappbase("dnpool_run");  //调用appbase中的下载池入口,通过Bind以及$全局变量的方法传入参数
        label(16,x1,y1,x2,y2,"loading....",15,63,0);
    }
    if (st==1){
        label(16,x1,y1,x2,y2,"",15,63,0);
        pic(x1,y1,picn);
        $dnpool_type=2; //启动下一个
        callappbase("dnpool_run"); //调用下载池启用下一个下载
    }
}

//事件:
void doWIFI() //处理bin下载完成之后的事件
{
    //wifi_httpdnbin
    str jurl;
    jurl=hook_get(0);    //url
    //获取URL,如果有多个不同的下载,可以通过URL来识别
    if (jurl==url){  //如果是a.jpg,则显示
        int size;
        size=hook_get(1);  //获取下载的a.jpg的实际尺寸
        jpg_decode(0xa0000,size,picn); //解码JPG到0号位置,该位置对应图片2048号
        st=1;    //下载完成
    }
}
执行步骤讲述:

页面上放置两个urljpg控件,分别是u1和u2,u1下载a.jpg; u2下载b.jpg