第一个weex任务:图片显示改为串行

问题

公司接入weex大概也有半年多的时间了,sdk的版本是0.6.4,自定义的组件一大堆。不过image这个组件一直没有自定义。
我们的应用有一个“发现”页面,全部是图片,用weex写的。交互抱怨图片加载后,乱显示的,体验很不好,希望一张一张有顺序地显示。
weex提供的image组件,图片下载要自己实现,demo程序是用SDWebImage做的,所以这边也是依样画葫芦。SDWebImage是用NSOperationQueue实现,默认并发数为3,是并行加载的,要求图片顺序显示,怎么可能?
所以,这个问题从去年底就提出来了,一直没人去管,并且还记下来一个坑:
目前图片加载顺序, 异步随机

方案1:Native层自定义组件

  • weex SDK<image>组件对应的Native类是WXImageComponent
  • 关于图片下载的过程,用了一个全局的串行队列,套了好几层主线程做下载任务分发。真正的下载过程,通过协议WXImageOperationProtocol让使用者来实现。
  • 一般实现都是通过SDWebImage这个第三方库来做的,下载图片是并行的,并发数默认是3
  • 估计是将SDWebImage这种第三方库引入weex框架,会导致框架本身太庞大,不合适。所以采用了协议加demo程序这种方式。
  • 图片下载过程采用并行方式是合理的,不然,串行下载,性能太差。
  • 不过,这里需求是图片顺序显示,那么进行串行下载是最方便的。既然采用SDWebImage这个第三方库,只要将它的最大并发数设置为1,编程串行队列下载,就可以了。、
  • 默认的image组件不变,可以参照写法,稍微改一下,新建一个串行的图片组件,比如seiral-image就可以了。自定义组件就可以直接用SDWebImage来实现,不需要WXImageOperationProtocol来过渡。为了不影响默认的image组件,下载过程不要用SDWebImage共享单例,而是新建一个实例变量来做,这样就互不影响。

方案2:通过opacity属性,串行显示图片

  • native层组件保持不变,在JavaScript层来控制
  • if指令不合适,这个隐藏和native的隐藏含义不一样,是整个结点都不创建,在这里不适用
  • 加载过程保持串行不变。加载完成后,native会发送load事件到JavaScript层。
  • 默认将图片的opacity设置为0,就算加载完成了,也看不到图片。在收到load事件后,将图片的opacity设置为1,显示图片。这时可以加入一些自定义的逻辑,比如顺序显示等。
  • 下面是一个简单的例子:
<template>
    <list>
        <cell class="cell">
            <image class="image" repeat="item in imageList" src="{{item.filePath}}" style="opacity:{{opacitys[$index]}}" onload="imageLoad($index)">                        
            </image>
        </cell>
    </list>
</template>

<style>
    .cell {
        height: 212px;
        flex-direction: row;
        justify-content: space-between;
        align-items: stretch;
        padding-top: 30px;
        padding-left: 24px;
        padding-right: 24px;
    }

    .image {
        width: 223px;
    }
</style>

<script >
    module.exports = {
        data: {
            imageList: [],
            loadFlags:[],
            opacitys:[]
        },
        created: function(){    
            this.onrefresh();
        },
        methods: {
            onrefresh: function(){
                this.displayRefreshing = 'show';
                this.refreshing = true;

                let stream = require("@weex-module/stream");
                var modal = require('@weex-module/modal');
                let self = this;
                stream.fetch({
                    url: "/app/image",
                    indicator: "silent",
                }, function(ret) { 
                    self.refreshing = false;
                    self.displayRefreshing = 'hide';
                    self.imageList = ret.imageList;

                    // 只是添加新的元素,旧的元素不更改。函数onrefresh()可能被反复调用,只要第一次将opacity由0变1,不反复更改
                    var startIndex = self.loadFlags.length;
                    for (var i = startIndex; i < ret.imageList.length; i++) {
                        self.loadFlags[i] = false;
                        self.opacitys.$set(i, 0);
                    }

                    // 设定超时保护(30秒),图片全部显示
                    setTimeout(function() {
                        self.dispalyAllImages()
                    }, 30000);

                }, function(err){
                    self.refreshing = false;
                    self.displayRefreshing = 'hide';
                    modal.toast({'message': '网络不给力,请稍后再试!', 'duration': 2});
                }
                );
            },
            imageLoad: function(index) {
                this.loadFlags[index] = true;
                this.updateImageOpacity();
            },
            updateImageOpacity: function() {
                // 图片顺序展示
                for (var i = 0; i < this.commonLoadFlags.length; i++) {
                    // 还没加载,就不显示; 要求顺序,后面的就不管了
                    if (false == this.commonLoadFlags[i]) {
                        break;
                    }
                    // 如果已经显示,就没必要重复设置
                    if (this.opacitys[i] > 0) {
                        continue;
                    }

                    this.opacitys.$set(i, 1);
                }
            },
            // 超时函数;加载状态不更新;但是显示状态全部设置为显示
            dispalyAllImages: function() {
                for (var i = 0; i < this.opacitys.length; i++) {
                    // 如果已经显示,就没必要重复设置
                    if (this.opacitys[i] > 0) {
                        continue;
                    }
                    this.opacitys.$set(i, 1);
                }
            }
        }
    }
</script>
  • imageList: [], 存放图片的信息,比如url就是其中的filePath属性
  • loadFlags:[], 存放加载状态信息,false- 图片还没加载;true-图片已经加载
  • opacitys:[],存放图片的opacity值,0-图片隐藏;1-图片显示
  • imageLoad(index)为load事件响应函数,native层触发,将图片的序号传给JavaScript
  • stream.fetch()native层实现,JavaScript层调用的网络取数据函数
  • array.$set(index, value),是weex框架提供数组设置函数,将index的值替换为value$set是函数名。用这个函数,可以结合weex框架内部的数据绑定机制,可以触发界面元素的重新渲染。
  • 在这里,初始化时self.opacitys.$set(i, 0);weex框架将图片渲染为不可见。当后来self.opacitys.$set(i, 1);``weex框架将图片渲染为可见。如果直接设置self.opacitys[i] = 0或者1,相应的数值值会改变,但是界面元素不会渲染,也就没有图片从一开始的不可见到可见的过程。
  • setTimeout函数先套一个匿名函数,然后用另一个变量,比如self来代替this,这样调用才有效果。记住这种用法。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容