当socket连接主推数据刷新频繁造成UI界面卡顿的一些思考

原文链接:http://www.jianshu.com/p/56fad765dcac

问题原因是有个点差列表的界面,前期是自己socket工具封装自己代码的失误,造成数据源data不断追加,比较专业的行情数据,都会定义规范的结构体,会返回当前数据包的长度,次数在于数据处理时可以处理一部分抛除一部分,但是本人实际项目中只是简单地返回的字符串的data数据,这样就算socket断包,我们也不方便处理,所以就简单地每次只处理接受的数据,(更合理的应该是用nsmutabledata不断的追加拼接数据,然后解包根据包头返回的实际内容的长度截取处理)

然后由于此列表 (交易商数*对应的交易品种)比较多,从而造成数据变化特别频繁,从而造成刷新列表的卡顿

主要修改的几个地方:
1.主推频繁,然后每次主推里边有循环处理数据,所以此处将数据处理放在了子线程中,数据处理好之后用代理或者block返回时拉回主线程

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
//    LOG(@".net行情数据~~~~~");
//    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(@"~~~点差数据:%@",str);
        self.socketData = [NSData dataWithData:data];
    }
    
    //常用方式异步并发+与主线程交互
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //耗时长的操作
        [self dealWithSocketData];//处理数据
        [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"]) {
            //数据格式 点差    点差类型(01),交易商Code,品名,点差
            //               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 只要符合的三个点差
                        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(@"~~~点差数据:%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"]){
         
            //数据格式 行情    行情类型(02),交易商Code,品名,买入价,卖出价,点差
            //               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

kPreventRepeatClickTime(0.5);//限制刷新频率,引起卡顿的问题是刷新频率太快,此处硬代码处理

-(void)reloadTableViewData{
    
    kPreventRepeatClickTime(0.5);//限制刷新频率,引起卡顿的问题是刷新频率太快,此处硬代码处理
    
    if (_isAllowRefresh) {
        
        dispatch_async(dispatch_get_main_queue(), ^{
            NSArray *cells = [self.tableView indexPathsForVisibleRows];//取出当前界面上的cell
            if (cells.count > 0 && self.dataArr.count > 0 && self.dataArr.count >= cells.count) {
                //主线程界面刷新
                [self.tableView reloadRowsAtIndexPaths:cells withRowAnimation:(UITableViewRowAnimationNone)];
//                 LOG(@"~~~reloadRowsAtIndexPaths~~~");
            }
        });
    }
}

3.设置开关,当列表拖动的时候不刷新

//开始拖动时禁止刷新
-(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];
    }
}
展开阅读全文

没有更多推荐了,返回首页