當(dāng)socket連接主推數(shù)據(jù)刷新頻繁造成UI界面卡頓的一些思考(限流)

問(wèn)題原因是有個(gè)點(diǎn)差列表的界面,前期是自己socket工具封裝自己代碼的失誤,造成數(shù)據(jù)源data不斷追加,比較專業(yè)的行情數(shù)據(jù),都會(huì)定義規(guī)范的結(jié)構(gòu)體,會(huì)返回當(dāng)前數(shù)據(jù)包的長(zhǎng)度,次數(shù)在于數(shù)據(jù)處理時(shí)可以處理一部分拋除一部分,但是本人實(shí)際項(xiàng)目中只是簡(jiǎn)單地返回的字符串的data數(shù)據(jù),這樣就算socket斷包,我們也不方便處理,所以就簡(jiǎn)單地每次只處理接受的數(shù)據(jù),(更合理的應(yīng)該是用nsmutabledata不斷的追加拼接數(shù)據(jù),然后解包根據(jù)包頭返回的實(shí)際內(nèi)容的長(zhǎng)度截取處理)

然后由于此列表 (交易商數(shù)*對(duì)應(yīng)的交易品種)比較多,從而造成數(shù)據(jù)變化特別頻繁,從而造成刷新列表的卡頓

主要修改的幾個(gè)地方:
1.主推頻繁,然后每次主推里邊有循環(huán)處理數(shù)據(jù),所以此處將數(shù)據(jù)處理放在了子線程中,數(shù)據(jù)處理好之后用代理或者block返回時(shí)拉回主線程

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
//    LOG(@".net行情數(shù)據(jù)~~~~~");
//    if(self.socketData == nil){
//        self.socketData = [[NSData alloc] init];
//    }
    
    NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    if ([dataStr containsString:@"Heart"]) {
//        LOG(@"心跳正常");
    }else{
        
//        NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//        LOG(@"~~~點(diǎn)差數(shù)據(jù):%@",str);
        self.socketData = [NSData dataWithData:data];
    }
    
    //常用方式異步并發(fā)+與主線程交互
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //耗時(shí)長(zhǎng)的操作
        [self dealWithSocketData];//處理數(shù)據(jù)
        [self.socket readDataWithTimeout:10 tag:tag];
    });
}

-(void)dealWithSocketData{
    
    if (![_socketData isKindOfClass:[NSData class]]) {
        return;
    }
    if (_socketData.length > 2) {
        
        NSString *dataStr = [[NSString alloc] initWithData:self.socketData encoding:NSUTF8StringEncoding];
        NSArray *strArr = [dataStr componentsSeparatedByString:@"#"];
        
        NSMutableArray *strMarry = [NSMutableArray arrayWithArray:strArr];
        [strMarry removeLastObject];
        NSString *str = strArr[0];
        NSString *typeStr = @"";
        if (str.length > 2) {
            typeStr = [str substringToIndex:2];
        }
        if (![typeStr isEqualToString:@"01"] && ![typeStr isEqualToString:@"02"]) {
            [strMarry removeObjectAtIndex:0];
        }
        
        str = strMarry[0];
        typeStr = [str substringToIndex:2];
        strArr = [NSArray arrayWithArray:strMarry];
        
        if ([typeStr isEqualToString:@"01"]) {
            //數(shù)據(jù)格式 點(diǎn)差    點(diǎn)差類型(01)袋倔,交易商Code劫映,品名什燕,點(diǎn)差
            //               01,000001674566,EURUSD,2.0
            
            NSMutableArray *xlSocketModelMArr = [NSMutableArray arrayWithCapacity:1];
            
            for (NSString *singleStr in strArr) {
                if (singleStr.length > 0) {
                    NSArray *valuesArr = [singleStr componentsSeparatedByString:@","];
                    NSString *type = valuesArr[0];
                    if ([type isEqualToString:@"01"]) {
                        
                        XLSocketModel *model = [XLSocketModel new];
                        
                        if (valuesArr.count > 2) {
                            model.n = valuesArr[2];
                        }
                        //此處修改邏輯 2017.12.14 只要符合的三個(gè)點(diǎn)差
                        if ([model.n isEqualToString:@"EURUSD"] || [model.n isEqualToString:@"XAUUSD"] || [model.n isEqualToString:@"OILUSD"]) {
                            if (valuesArr.count > 1) {
                                model.traderCode = valuesArr[1];
                            }
                            if (valuesArr.count > 3) {
                                model.spread = valuesArr[3];
                            }
                            [xlSocketModelMArr addObject:model];
//                             LOG(@"~~~點(diǎn)差數(shù)據(jù):%li~~",xlSocketModelMArr.count);
                        }else{
                            continue;
                        }
                    }
                }
            }

            dispatch_async(dispatch_get_main_queue(), ^{
                //主線程界面刷新
                if (self.allTraderSpreadDataBlock) {
                    self.allTraderSpreadDataBlock(xlSocketModelMArr);
                }
                if (self.singleTraderCodeSpreadDataBlock) {
                    self.singleTraderCodeSpreadDataBlock(xlSocketModelMArr);
                }
            });
            
        }else if ([typeStr isEqualToString:@"02"]){
         
            //數(shù)據(jù)格式 行情    行情類型(02)例证,交易商Code,品名涕蜂,買入價(jià)析校,賣出價(jià),點(diǎn)差
            //               02,000001674566长酗,EURUSD,2.1345,3.12344,28
            NSMutableArray *xlSocketModelMArr = [NSMutableArray arrayWithCapacity:1];
            for (NSString *singleStr in strArr) {
                if (singleStr.length > 0) {
                    NSArray *valuesArr = [singleStr componentsSeparatedByString:@","];
                    NSString *type = valuesArr[0];
                    if ([type isEqualToString:@"02"]) {
                        
                        XLSocketModel *model = [XLSocketModel new];
                        model.traderCode = valuesArr[1];
                        model.n = valuesArr[2];
                        model.bid = valuesArr[3];
                        model.sel = valuesArr[4];
                        model.spread = valuesArr[5];
                        [xlSocketModelMArr addObject:model];
                    }
                }
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                //主線程界面刷新
                if (self.singleTraderMarketDataBlock) {
                    self.singleTraderMarketDataBlock(xlSocketModelMArr);
                }
            });
            
        }
    }
    
}

2.限制刷新頻率+只刷新界面上的cell

(1) kPreventRepeatClickTime(0.5);//限制刷新頻率,引起卡頓的問(wèn)題是刷新頻率太快,此處硬代碼處理

// 防止多次調(diào)用
#define kPreventRepeatClickTime(_seconds_) \
static BOOL shouldPrevent; \
if (shouldPrevent) return; \
shouldPrevent = YES; \
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((_seconds_) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ \
shouldPrevent = NO; \
}); \

(2)MessageThrottle,限流控制刷新頻率,參考http://www.reibang.com/p/5dacd8778a5a

-(void)reloadTableViewData{

//(1.)限制刷新頻率,引起卡頓的問(wèn)題是刷新頻率太快,此處硬代碼處理    
  kPreventRepeatClickTime(0.5);

//(2.)限制刷新的頻率 xinle
        [self mt_limitSelector:@selector(tableViewReloadData) oncePerDuration:(0.10)];
    
    if (_isAllowRefresh) {
        
        dispatch_async(dispatch_get_main_queue(), ^{
            NSArray *cells = [self.tableView indexPathsForVisibleRows];//取出當(dāng)前界面上的cell
            if (cells.count > 0 && self.dataArr.count > 0 && self.dataArr.count >= cells.count) {
                //主線程界面刷新
                [self.tableView reloadRowsAtIndexPaths:cells withRowAnimation:(UITableViewRowAnimationNone)];
//                 LOG(@"~~~reloadRowsAtIndexPaths~~~");
            }
        });
    }
}

3.設(shè)置開關(guān),當(dāng)列表拖動(dòng)的時(shí)候不刷新

//開始拖動(dòng)時(shí)禁止刷新
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    if ([scrollView class] == [self.tableView class]) {
        self.isAllowRefresh = 0;
    }
}
//減速完畢
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    if ([scrollView class] == [self.tableView class]) {
        self.isAllowRefresh = 1;
    }
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if ([scrollView class] == [self.tableView class]) {
        if (!decelerate) {
            self.isAllowRefresh = 1;
        }
        [self getAllTraderSPread];
    }
}

tableview刷新可以考慮cell通知監(jiān)聽單刷,不用整個(gè)tableview整體刷新

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末溪北,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子夺脾,更是在濱河造成了極大的恐慌之拨,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咧叭,死亡現(xiàn)場(chǎng)離奇詭異蚀乔,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)佳簸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門乙墙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)颖变,“玉大人,你說(shuō)我怎么就攤上這事听想⌒壬玻” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵汉买,是天一觀的道長(zhǎng)衔峰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蛙粘,這世上最難降的妖魔是什么垫卤? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮出牧,結(jié)果婚禮上穴肘,老公的妹妹穿的比我還像新娘。我一直安慰自己舔痕,他們只是感情好评抚,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伯复,像睡著了一般慨代。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上啸如,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天侍匙,我揣著相機(jī)與錄音,去河邊找鬼叮雳。 笑死想暗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的债鸡。 我是一名探鬼主播江滨,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼厌均!你這毒婦竟也來(lái)了唬滑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤棺弊,失蹤者是張志新(化名)和其女友劉穎晶密,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體模她,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡稻艰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了侈净。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尊勿。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡僧凤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出元扔,到底是詐尸還是另有隱情躯保,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布澎语,位于F島的核電站途事,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏擅羞。R本人自食惡果不足惜尸变,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望减俏。 院中可真熱鬧召烂,春花似錦、人聲如沸垄懂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)草慧。三九已至,卻和暖如春匙头,著一層夾襖步出監(jiān)牢的瞬間漫谷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工蹂析, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舔示,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓电抚,卻偏偏與公主長(zhǎng)得像惕稻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蝙叛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

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