第一個(gè)weex任務(wù):圖片顯示改為串行

問題

公司接入weex大概也有半年多的時(shí)間了超埋,sdk的版本是0.6.4卦溢,自定義的組件一大堆。不過image這個(gè)組件一直沒有自定義泵殴。
我們的應(yīng)用有一個(gè)“發(fā)現(xiàn)”頁面涮帘,全部是圖片,用weex寫的笑诅。交互抱怨圖片加載后调缨,亂顯示的,體驗(yàn)很不好吆你,希望一張一張有順序地顯示弦叶。
weex提供的image組件,圖片下載要自己實(shí)現(xiàn)妇多,demo程序是用SDWebImage做的伤哺,所以這邊也是依樣畫葫蘆。SDWebImage是用NSOperationQueue實(shí)現(xiàn)者祖,默認(rèn)并發(fā)數(shù)為3立莉,是并行加載的,要求圖片順序顯示七问,怎么可能桃序?
所以,這個(gè)問題從去年底就提出來了烂瘫,一直沒人去管,并且還記下來一個(gè)坑:
目前圖片加載順序, 異步隨機(jī)

方案1:Native層自定義組件

  • weex SDK<image>組件對(duì)應(yīng)的Native類是WXImageComponent
  • 關(guān)于圖片下載的過程,用了一個(gè)全局的串行隊(duì)列坟比,套了好幾層主線程做下載任務(wù)分發(fā)芦鳍。真正的下載過程,通過協(xié)議WXImageOperationProtocol讓使用者來實(shí)現(xiàn)葛账。
  • 一般實(shí)現(xiàn)都是通過SDWebImage這個(gè)第三方庫(kù)來做的柠衅,下載圖片是并行的,并發(fā)數(shù)默認(rèn)是3
  • 估計(jì)是將SDWebImage這種第三方庫(kù)引入weex框架籍琳,會(huì)導(dǎo)致框架本身太龐大菲宴,不合適。所以采用了協(xié)議加demo程序這種方式趋急。
  • 圖片下載過程采用并行方式是合理的喝峦,不然,串行下載呜达,性能太差谣蠢。
  • 不過,這里需求是圖片順序顯示查近,那么進(jìn)行串行下載是最方便的眉踱。既然采用SDWebImage這個(gè)第三方庫(kù),只要將它的最大并發(fā)數(shù)設(shè)置為1霜威,編程串行隊(duì)列下載谈喳,就可以了。戈泼、
  • 默認(rèn)的image組件不變婿禽,可以參照寫法,稍微改一下矮冬,新建一個(gè)串行的圖片組件谈宛,比如seiral-image就可以了。自定義組件就可以直接用SDWebImage來實(shí)現(xiàn)胎署,不需要WXImageOperationProtocol來過渡吆录。為了不影響默認(rèn)的image組件,下載過程不要用SDWebImage共享單例琼牧,而是新建一個(gè)實(shí)例變量來做恢筝,這樣就互不影響。

方案2:通過opacity屬性巨坊,串行顯示圖片

  • native層組件保持不變撬槽,在JavaScript層來控制
  • if指令不合適,這個(gè)隱藏和native的隱藏含義不一樣趾撵,是整個(gè)結(jié)點(diǎn)都不創(chuàng)建侄柔,在這里不適用
  • 加載過程保持串行不變共啃。加載完成后,native會(huì)發(fā)送load事件到JavaScript層暂题。
  • 默認(rèn)將圖片的opacity設(shè)置為0移剪,就算加載完成了,也看不到圖片薪者。在收到load事件后纵苛,將圖片的opacity設(shè)置為1,顯示圖片言津。這時(shí)可以加入一些自定義的邏輯攻人,比如順序顯示等。
  • 下面是一個(gè)簡(jiǎn)單的例子:
<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;

                    // 只是添加新的元素悬槽,舊的元素不更改怀吻。函數(shù)onrefresh()可能被反復(fù)調(diào)用,只要第一次將opacity由0變1陷谱,不反復(fù)更改
                    var startIndex = self.loadFlags.length;
                    for (var i = startIndex; i < ret.imageList.length; i++) {
                        self.loadFlags[i] = false;
                        self.opacitys.$set(i, 0);
                    }

                    // 設(shè)定超時(shí)保護(hù)(30秒)烙博,圖片全部顯示
                    setTimeout(function() {
                        self.dispalyAllImages()
                    }, 30000);

                }, function(err){
                    self.refreshing = false;
                    self.displayRefreshing = 'hide';
                    modal.toast({'message': '網(wǎng)絡(luò)不給力,請(qǐng)稍后再試烟逊!', '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;
                    }
                    // 如果已經(jīng)顯示宪躯,就沒必要重復(fù)設(shè)置
                    if (this.opacitys[i] > 0) {
                        continue;
                    }

                    this.opacitys.$set(i, 1);
                }
            },
            // 超時(shí)函數(shù)乔宿;加載狀態(tài)不更新;但是顯示狀態(tài)全部設(shè)置為顯示
            dispalyAllImages: function() {
                for (var i = 0; i < this.opacitys.length; i++) {
                    // 如果已經(jīng)顯示访雪,就沒必要重復(fù)設(shè)置
                    if (this.opacitys[i] > 0) {
                        continue;
                    }
                    this.opacitys.$set(i, 1);
                }
            }
        }
    }
</script>
  • imageList: [], 存放圖片的信息详瑞,比如url就是其中的filePath屬性
  • loadFlags:[], 存放加載狀態(tài)信息,false- 圖片還沒加載臣缀;true-圖片已經(jīng)加載
  • opacitys:[]坝橡,存放圖片的opacity值,0-圖片隱藏精置;1-圖片顯示
  • imageLoad(index)為load事件響應(yīng)函數(shù)计寇,native層觸發(fā),將圖片的序號(hào)傳給JavaScript
  • stream.fetch()脂倦,native層實(shí)現(xiàn)番宁,JavaScript層調(diào)用的網(wǎng)絡(luò)取數(shù)據(jù)函數(shù)
  • array.$set(index, value),是weex框架提供數(shù)組設(shè)置函數(shù)赖阻,將index的值替換為value蝶押。$set是函數(shù)名。用這個(gè)函數(shù)火欧,可以結(jié)合weex框架內(nèi)部的數(shù)據(jù)綁定機(jī)制棋电,可以觸發(fā)界面元素的重新渲染茎截。
  • 在這里,初始化時(shí)self.opacitys.$set(i, 0);离陶,weex框架將圖片渲染為不可見稼虎。當(dāng)后來self.opacitys.$set(i, 1);``weex框架將圖片渲染為可見。如果直接設(shè)置self.opacitys[i] = 0或者1招刨,相應(yīng)的數(shù)值值會(huì)改變,但是界面元素不會(huì)渲染哀军,也就沒有圖片從一開始的不可見到可見的過程沉眶。
  • setTimeout函數(shù)先套一個(gè)匿名函數(shù),然后用另一個(gè)變量杉适,比如self來代替this谎倔,這樣調(diào)用才有效果。記住這種用法猿推。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末片习,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蹬叭,更是在濱河造成了極大的恐慌藕咏,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秽五,死亡現(xiàn)場(chǎng)離奇詭異孽查,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)坦喘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門盲再,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瓣铣,你說我怎么就攤上這事答朋。” “怎么了棠笑?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵梦碗,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我腐晾,道長(zhǎng)叉弦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任藻糖,我火速辦了婚禮淹冰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘巨柒。我一直安慰自己樱拴,他們只是感情好柠衍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著晶乔,像睡著了一般珍坊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上正罢,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天阵漏,我揣著相機(jī)與錄音,去河邊找鬼翻具。 笑死履怯,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的裆泳。 我是一名探鬼主播叹洲,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼工禾!你這毒婦竟也來了运提?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤闻葵,失蹤者是張志新(化名)和其女友劉穎民泵,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體笙隙,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡洪灯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了竟痰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片签钩。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖坏快,靈堂內(nèi)的尸體忽然破棺而出铅檩,到底是詐尸還是另有隱情,我是刑警寧澤莽鸿,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布昧旨,位于F島的核電站,受9級(jí)特大地震影響祥得,放射性物質(zhì)發(fā)生泄漏兔沃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一级及、第九天 我趴在偏房一處隱蔽的房頂上張望乒疏。 院中可真熱鬧,春花似錦饮焦、人聲如沸怕吴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽转绷。三九已至伟件,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間议经,已是汗流浹背斧账。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留煞肾,地道東北人其骄。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像扯旷,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子索抓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容