讓列表加載如飄柔般順滑之預(yù)加載

最近在做項目時發(fā)現(xiàn)列表分頁加載數(shù)據(jù)體驗并不是很好牧愁,第一個想到解決此問題的方案就是預(yù)加載,便在網(wǎng)上找了一些相關(guān)的資料還有 demo 試過之后發(fā)現(xiàn)效果不是很好而且好多細節(jié)都沒有處理好外莲,便想著自己寫個 demo 實現(xiàn)預(yù)加載猪半,因為平時項目比較忙寫這個demo 都是平時下班時間寫一點,寫了蠻長時間的偷线。今天把 demo 中實現(xiàn)的一些細節(jié)和學(xué)習(xí)資料分享給大家磨确。沒有耐心讀的同學(xué)可以直接翻到底即可下載 demo

來瞅一眼效果圖,一圖勝千言声邦。

預(yù)加載.gif

依賴三方庫

AFNetworking用于網(wǎng)絡(luò)請求

MJRefresh用于刷新

YYKit用于模型轉(zhuǎn)換乏奥,也可以直接用YYModel或者MJExtension

ReactiveObjC用于數(shù)據(jù)的傳輸 (大家平時用的應(yīng)該都是 block 去傳遞數(shù)據(jù)吧,當寫完這個 demo 的時候也用 block 去實現(xiàn)了網(wǎng)絡(luò)請求傳遞數(shù)據(jù)后來又刪掉了亥曹,因為 block 在傳遞數(shù)據(jù)的時候沒有 reactive 優(yōu)雅邓了。如果有同學(xué)對此三方庫不了解,可自行實現(xiàn)數(shù)據(jù)傳遞部分)

MBProgressHUD不需要的可以移除掉

項目中常見問題:

相信你所做的項目中有很多是用 Tableview 或 Collectionview 所展示的數(shù)據(jù)列表媳瞪,做列表展示時會一些常見問題:

  • 每次滑動到底部時都要去加載下一頁的數(shù)據(jù)骗炉,每次都是菊花轉(zhuǎn)啊轉(zhuǎn)用戶體驗并不是很好,如何下拉刷新時加載菊花上拉加載時不加載菊花(MBProgressHUD)蛇受。

  • 每次都要定義一個全局的currentPagetotlePage來計算當前頁是否小于總頁句葵,而且需要不斷的從接口拿取頁碼數(shù)據(jù),比如這種數(shù)據(jù):

      "page":{
              "totalResultSize":27,
             "totalPageSize":3,
             "pageSize":10,
             "currentPage":1,
              }
    

每次網(wǎng)絡(luò)請求時總需要把頁碼信息拿出來用來判斷是否發(fā)起網(wǎng)絡(luò)請求,這樣寫很繁瑣有木有

  • 每次網(wǎng)絡(luò)請求的時候要判斷是否是刷新還是獲取新數(shù)據(jù)來對接受數(shù)據(jù)的數(shù)組來做移除或添加操作乍丈。獲取數(shù)據(jù)后刷新UI是不是有卡頓的現(xiàn)象剂碴,總說數(shù)據(jù)和刷新 UI 要分開操作,刷新 UI 要放到主線程去做轻专,可是你真的是這么做的嗎忆矛?你的數(shù)據(jù)處理真的是放到子線程去的嗎?

  • MJRefresh去刷新列表的時候你是否是這么操作的铭若?結(jié)束刷新操作不是應(yīng)該放在獲取到數(shù)據(jù)之后才做的嗎洪碳?

      self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
      //通過這個狀態(tài)來判斷對接受數(shù)據(jù)的數(shù)組來做移除或添加操作
      weakSelf.addData = NO;
      //將頁碼重置
      weakSelf.currentPage = 1;
      //發(fā)起網(wǎng)絡(luò)請求
      [weakSelf loadDiscoverData];
      //立刻結(jié)束刷新狀態(tài),即關(guān)閉菊花
      [weakSelf.tableView.mj_header endRefreshing];
      
      }];
    

解決問題

帶著這些問題我們來慢慢找尋一下解決辦法叼屠。

  • 如何每次網(wǎng)絡(luò)能請求兩頁數(shù)據(jù)瞳腌,當滑動到列表的某一位置來發(fā)起網(wǎng)絡(luò)請求。你可以去網(wǎng)上搜一下相關(guān)的關(guān)鍵詞镜雨,差不多會得到兩種結(jié)果①利用 scrollview 的代理來計算內(nèi)容高度嫂侍;②利用indexPath的下標與數(shù)據(jù)源判斷是否發(fā)起網(wǎng)絡(luò)請求。是的荚坞,我用的就是第二種挑宠,不需要繁瑣的計算。

由于發(fā)起了兩次網(wǎng)絡(luò)請求颓影,列表會刷新兩次各淀,如果網(wǎng)絡(luò)條件不是很好的情況下頁面刷新不及時會卡一下,由于用的是MBProgressHUD做的提示诡挂,當每次請求的時候會在屏幕中間加載旋轉(zhuǎn)菊花碎浇,每次發(fā)起網(wǎng)絡(luò)請求菊花旋轉(zhuǎn)時間比請求一次的時候要長。針對這一情況璃俗,我在網(wǎng)絡(luò)請求工具中設(shè)置了是否顯示菊花奴璃,關(guān)于我封裝的網(wǎng)絡(luò)請求介紹可以看這篇文章,里面有詳細的使用介紹城豁。

在網(wǎng)絡(luò)請求使用類MNetConfig中加入了isHidenHUD,這與下拉和上拉狀態(tài)取反達到異曲同工之妙苟穆。

/** *是否顯示HUD,默認顯示*/
@property (nonatomic, assign) BOOL isHidenHUD;
  • 如何不用傳頁碼參數(shù)來判斷當前數(shù)據(jù)是第幾頁數(shù)據(jù),如何獲取到?jīng)]有更多數(shù)據(jù)的狀態(tài)唱星。

我將網(wǎng)絡(luò)請求和數(shù)據(jù)的處理從控制器中抽離出來即MVVM中的VM雳旅,具體關(guān)于MVVM設(shè)計模式請自行查詢,這里就不做過多闡述间聊。我通過對NSObject類進行了Category岭辣,抽離出一個專門處理網(wǎng)絡(luò)請求數(shù)據(jù)的類NSObject+MRequestAdd.h來看一下我針對網(wǎng)絡(luò)請求設(shè)置了哪些屬性:

/**
 *  數(shù)據(jù)數(shù)組
 */
@property (nonatomic, strong) NSMutableArray *dataArray;
/**
 *  原始請求數(shù)據(jù)
 */
@property (nonatomic, strong) id orginResponseObject;
/**
 *  當前頁碼
 */
@property (nonatomic, assign) NSInteger currentPage;
/**
 *  是否請求中
 */
@property (nonatomic, assign) BOOL isRequesting;
/**
 *  是否數(shù)據(jù)加載完
 */
@property (nonatomic, assign) BOOL isNoMoreData;

-(RACSignal *)singalForSingleRequestWithSet:(MNetConfig *)setting;

如果你寫過類的Category會發(fā)現(xiàn)分類是不允許property的。

如果你寫一個屬性會在.m中出現(xiàn)黃色警告甸饱,要么將這個屬性標記為@dynamic要么實現(xiàn)setget方法,就算實現(xiàn)了 set 和 get 方法在調(diào)用的時候也可能報錯。

Property 'test' requires method 'setTest:' to be defined 
- use @dynamic or provide a method implementation in this category

這時就需要用到runtime了叹话,可能你感覺這個東西很虛無縹緲而且不好懂(像我這種初學(xué)者)如果你資料看多了也就慢慢懂了偷遗,下面給同學(xué)們普及一點點 runtime 的一些知識,本人理解的比較淺如有哪里不對的地方請留言給我驼壶。

runtime 能為類做些什么

  1. 為現(xiàn)有的類添加私有變量氏豌,比如在網(wǎng)絡(luò)請求時來判斷網(wǎng)絡(luò)請求是否加載完成
    @property (nonatomic, assign) BOOL isNoMoreData;

  2. 為現(xiàn)有的類添加共有屬性供外部訪問。

     @property (nonatomic, strong) NSMutableArray *dataArray;
    
  3. 為 KVO 創(chuàng)建一個關(guān)聯(lián)的觀察者热凹,這個屬性我還沒有用到泵喘,具體怎么用我也不是很清楚,這個用法也是資料說的般妙。

第一點與第二點的區(qū)別無非是一個公有和私有的區(qū)別纪铺,從本質(zhì)創(chuàng)建上并么有太大區(qū)別,我在項目中用的最多的也是這兩點碟渺。

創(chuàng)建 runtime 屬性:你可以在#import <objc/runtime.h>找到它們

objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,id _Nullable value, objc_AssociationPolicy policy)
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)
objc_removeAssociatedObjects(id _Nonnull object) 

從字面上你應(yīng)該可以猜到了鲜锚,

objc_setAssociatedObject是一個 set 方法,重寫 set 方法相信大家都寫過苫拍,這個用法與之類似芜繁,是用于給對象添加關(guān)聯(lián)對象
objc_getAssociatedObject獲取關(guān)聯(lián)對象
objc_removeAssociatedObjects移除一個對象的所有關(guān)聯(lián)對象

objc_setAssociatedObject

objc_setAssociatedObject會涉及到四個參數(shù),分別是object绒极、key骏令、valuepolicy

  1. object垄提,要關(guān)聯(lián)的對象即 self

  2. key 榔袋,這個 key 值必須保證是一個對象級別的唯一常量與創(chuàng)建 tablviewcell 所創(chuàng)建的 ID 類似;一般來說塔淤,有以下三種推薦的 key 值:① 聲明 static const char * key_m_dataArray = "key_m_dataArray";使用 &key_m_dataArray 作為 key 值這個是需要加&符號獲取地址;② 聲明 static const void * key_m_dataArray = "key_m_dataArray" 摘昌,使用 key_m_dataArray 作為 key 值;③ 用 selector 高蜂,使用 getter 方法的名稱作為 key 值聪黎。因為它省掉了一個變量名,非常優(yōu)雅地解決了命名問題备恤。

  3. value 即當前屬性的值

  4. policy 關(guān)聯(lián)策略

     typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
         OBJC_ASSOCIATION_ASSIGN = 0,//弱引用對象
         OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //強引用對象且為非原子操作
         OBJC_ASSOCIATION_COPY_NONATOMIC = 3,//復(fù)制關(guān)聯(lián)對象且為非原子操作
         OBJC_ASSOCIATION_RETAIN = 01401,//強引用對象且為原子操作         
         OBJC_ASSOCIATION_COPY = 01403//復(fù)制關(guān)聯(lián)對象為原子操作
     };
     將前三種翻譯過來即:
     @property (nonatomic, assign)
     @property (nonatomic, strong)
     @property (nonatomic, copy)
    

關(guān)聯(lián)對象的五種關(guān)聯(lián)策略與屬性的限定符非常類似稿饰,在絕大多數(shù)情況下,我們都會使用 OBJC_ASSOCIATION_RETAIN_NONATOMIC 的關(guān)聯(lián)策略露泊,這可以保證我們持有關(guān)聯(lián)對象喉镰。

關(guān)于Associated Objects是如何實現(xiàn)以及如何儲存數(shù)據(jù)和關(guān)聯(lián)對象建議你看一下這篇文章或許對你有幫助。關(guān)于 runtime 的一些知識就介紹那么多惭笑,現(xiàn)在我對 runtime 只是會用一些簡單的屬性而更深層次的用法我也在探索中侣姆。

回到NSObject+MRequestAdd這個類中來生真,看一下內(nèi)部實現(xiàn)。

通過-(RACSignal *)singalForSingleRequestWithSet:(MNetConfig *)setting;這個方法來進行網(wǎng)絡(luò)請求捺宗,而每次網(wǎng)絡(luò)請求是通過下面的方法來實現(xiàn)的

- (RACSignal *)baseSingleRequestWithSet:(MNetConfig *)setting{
    RACReplaySubject *subject = [RACReplaySubject subject];
    //判斷當前網(wǎng)絡(luò)狀態(tài)柱蟀,是否已經(jīng)在請求數(shù)據(jù)或者沒有更多數(shù)據(jù)時返回 error 狀態(tài),表示沒有數(shù)據(jù)或請求失敗
    if (![self isSatisfyLoadMoreRequest]&&!setting.isRefresh) {
        [subject sendError:nil];
        return subject;
    }
    //避免某些接口只有 page 一個參數(shù)蚜厉,所以需要初始化一個 parameter 來存放 page 字段
    if (!setting.paramet) {
        setting.paramet = [NSMutableDictionary dictionary];
    }
    if (setting.isRefresh) {
        self.currentPage = 0;
    }
    self.currentPage ++;
    if (setting.keyOfPage) {
      [setting.paramet setValue:@(self.currentPage) forKey:setting.keyOfPage];
    }
    //每一次網(wǎng)絡(luò)請求都是YES长已,請求完畢就為 NO
    self.isRequesting = YES;
    [[MNetRequestModel netRequestSeting:setting] subscribeNext:^(id  _Nullable x) {
        self.isRequesting = NO;
        [subject sendNext:x];
        
    } error:^(NSError * _Nullable error) {
        self.isRequesting = NO;
        //如果當前請求失敗,因為都是在原來頁碼上進行++昼牛,所以這里需要--來回退頁碼术瓮。
        if (self.currentPage > 0) {
            self.currentPage--;
        }
        [subject sendError:error];
    } completed:^{
        [subject sendCompleted];
    }];
    return subject;
    
}
- (BOOL)isSatisfyLoadMoreRequest{
return (!self.isNoMoreData&&!self.isRequesting);
}   

再來看一下.h 文件放出的接口的實現(xiàn)

- (RACSignal *)singalForSingleRequestWithSet:(MNetConfig *)setting{
    RACReplaySubject *subject = [RACReplaySubject subject];
    //每次調(diào)用的即是上面所寫的方法,每次有新數(shù)據(jù)時才會走網(wǎng)絡(luò)請求贰健,如果沒有走 error 狀態(tài)胞四,即沒有數(shù)據(jù)表示已無更多數(shù)據(jù)
    [[self baseSingleRequestWithSet:setting] subscribeNext:^(id  _Nullable x) {
        //每一次請求到的源數(shù)據(jù)
        self.orginResponseObject = x;
        //利用 runtime 創(chuàng)建的屬性來初始化
        if (!self.dataArray) {
            self.dataArray = @[].mutableCopy;
        }
        if (setting.isRefresh) {
            [self.dataArray removeAllObjects];
        }
        //定位到要解析的數(shù)據(jù)位置,用“/”做拆分
        NSArray *separateKeyArray = [setting.modelLocalPath componentsSeparatedByString:@"/"];
        for (NSString *sepret_key in separateKeyArray) {
            x = x[sepret_key];
        }
        //每一次網(wǎng)絡(luò)請求獲取的模型數(shù)據(jù)
        NSArray *dataArray = [NSArray modelArrayWithClass:NSClassFromString(setting.modelNameOfArray) json:x];
        //如果當前請求到的數(shù)據(jù)為空霎烙,說明網(wǎng)絡(luò)出錯或者沒有更多數(shù)據(jù)
        if (dataArray.count == 0) {
            self.isNoMoreData = YES;
            [subject sendError:nil];
        } else {
        //只有有數(shù)據(jù)時才進行 sendnext撬讽,即傳遞數(shù)據(jù)
            self.isNoMoreData = NO;
            [self.dataArray addObjectsFromArray:dataArray];
            [subject sendNext:self.dataArray];
        }
        
    } error:^(NSError * _Nullable error) {
        [subject sendError:error];
    }completed:^{
        [subject sendCompleted];
    }];
    return subject;
}

當前操作就完美解決了每次都要去處理接口中的 page 信息問題⌒看一下如何請求:

- (RACSignal *)siganlForTopicDataIsReload:(BOOL)isReload{

    RACReplaySubject *subject = [RACReplaySubject subject];
    MNetConfig *seting = [MNetConfig new];
    seting.hostUrl = Test_Page_URL;
    //    seting.paramet = @{};//如果有頁碼參數(shù),不要寫到字典,將頁碼參數(shù)寫到下方
        seting.modelLocalPath = @"entity/topics";//數(shù)據(jù)定位,即 entity 下的 topics 對應(yīng)的數(shù)據(jù)
        seting.keyOfPage = @"page.currentPage";//頁碼寫這
        seting.modelNameOfArray = @"MHYTestModel";//要顯示列表對應(yīng)的數(shù)據(jù)模型
        seting.isRefresh = isReload;//是否刷新
        seting.isHidenHUD = !isReload;//上拉刷新顯示 HUD 上拉更多不顯示 HUD
        //    seting.cashSeting = MCacheSave;// 是否進行本地緩存
        //    seting.cashTime = 4;//設(shè)置緩存時間為4分鐘,默認3分鐘
        //    seting.isCashMoreData = YES;//進行多頁數(shù)據(jù)緩存
    
    seting.jsonValidator = @{@"entity":[NSDictionary class],
                             @"entity":@{@"topics":[NSArray class]}
                             };//檢測 entity 是否為字典類型,檢測 entity 下 topics 字段是否為數(shù)組
    [[self singalForSingleRequestWithSet:seting]subscribeNext:^(id  _Nullable x) {
        [subject sendNext:x];
    } error:^(NSError * _Nullable error) {
        [subject sendError:error];
    } completed:^{
        [subject sendCompleted];
    }];
    return subject;
}

獲取到的數(shù)據(jù)如何正在子線程去處理呢游昼?
我在每一個網(wǎng)絡(luò)請求中加入了一個線程,可以看一下MNetRequestModel.m這個文件尝蠕,demo 中所有的網(wǎng)絡(luò)請求最終的請求都是它來完成的烘豌。

dispatch_async (dispatch_get_global_queue 
(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //獲取數(shù)據(jù)發(fā)送 next,處理數(shù)據(jù)
        [subject sendNext];
        dispatch_async (dispatch_get_main_queue(), ^{
        //再發(fā)送完成信號看彼,來刷新 UI
        [subject sendCompleted];
  });
});

這樣就將數(shù)據(jù)處理和 UI 刷新分開廊佩。

回過頭來看一下解決了哪些問題:刷新菊花顯示問題;處理頁碼問題靖榕;刷新 UI 問題标锄,和 mj 停止刷新時機問題(即在發(fā)送 comply 后停止刷新),以上羅列的問題都解決了茁计。

其實這樣做還有一些問題:如果非列表數(shù)據(jù)請求因為在所有網(wǎng)絡(luò)請求中加入了線程料皇,有一些信息是在 next 中獲取的比如接口中的message信息,這些信息需要給用戶來展示星压,如果在 next 中調(diào)用MBProgressHUD的 show 方法是崩潰的践剂,因為MBProgressHUD的菊花必須要的主線程中才可以調(diào)用。我是這樣處理的娜膘,為NSString
類寫一個分類逊脯,里面的方法大概就這么寫:

-(void)showSucceed;
-(void)showSucceed{
    dispatch_async(dispatch_get_main_queue(), ^{
        [MBProgressHUD showSuccess:self];
    });
}

如果信息和 UI 必須放在一起刷新,比如UIButton的狀態(tài)和文字改變竣贪,這時必須在當前文件中來創(chuàng)建中間替換變量再刷新 UI军洼。

還有一個最大的問題就是每次獲取到的數(shù)據(jù)都是總數(shù)據(jù)巩螃。如果要對模型做計算處理比如通過模型計算 cell 中的控件的 frame,第一頁獲取10條數(shù)據(jù)匕争,對模型做10次計算牺六,再請求10條數(shù)據(jù),此時應(yīng)該處理請求下來的10條數(shù)據(jù)汗捡,而數(shù)據(jù)處理是在 next 中完成的,next 中為總數(shù)據(jù)即20條數(shù)據(jù)畏纲,這樣模型的計算就進行了20次扇住,隨著頁面的增加計算量越來越大。這個問題我暫時還沒想到好的解決辦法盗胀,如果你有好的解決辦法請私信我艘蹋。

創(chuàng)建UITableView的 runtime 屬性

寫一個UITableView的分類UITableView+MPreload,創(chuàng)建倆個屬性:

/** tableview數(shù)據(jù) */
@property (nonatomic, strong) NSMutableArray *dataArray;
/** 預(yù)加載回調(diào)*/
@property (nonatomic, copy) PreloadBlock m_preloadBlock;

一個常量:

/**  預(yù)加載觸發(fā)的數(shù)量 */
static NSInteger const PreloadMinCount = 3;

和一個公開方法:

- (void)preloadDataWithCurrentIndex:(NSInteger)currentIndex;

- (void)preloadDataWithCurrentIndex:(NSInteger)currentIndex{
    NSInteger totalCount = self.dataArray.count;
    //判斷當前行數(shù)是否滿足預(yù)加載的條件
    if ([self isSatisfyPreloadDataWithTotalCount:totalCount currentIndex:currentIndex]&&self.m_preloadBlock) {
        //通過 block 來調(diào)用網(wǎng)絡(luò)請求
        self.m_preloadBlock();
    }
}

- (BOOL)isSatisfyPreloadDataWithTotalCount:(NSInteger)totalCount currentIndex:(NSInteger)currentIndex{
    //如果預(yù)加載觸發(fā)的數(shù)量為3票灰,總數(shù)據(jù)為10條即第7行觸發(fā)預(yù)加載
    return  ((currentIndex == totalCount - PreloadMinCount) && (currentIndex >= PreloadMinCount));
}

更具體的代碼請看 demo 中UITableView+MPreload文件

捋一下整體思路:

抽出一個專門做數(shù)據(jù)請求的類TestDataModel繼承與NSObject類型女阀,對NSObject利用 runtime 特性進行擴展屬性得到每次請求到的總數(shù)據(jù)dataArray,這樣TestDataModel類所創(chuàng)建的對象都可以擁有當前屬性屑迂,然后再利用 runtime 特性對UITableView進行擴展分別是兩個屬性dataArray浸策、m_preloadBlock一個方法- (void)preloadDataWithCurrentIndex:(NSInteger)currentIndex這樣每滑動 tablview 就會調(diào)用該方法灿椅,通過判斷是否進行預(yù)加載行為拢军,預(yù)加載請求的數(shù)據(jù)通過對象再給 tablview 的dataArray。其實思路很簡單,runtime擴展所需要的屬性和方法,然后有機的結(jié)合調(diào)用山上,這樣彼此循環(huán)調(diào)用就能創(chuàng)建一個無限循環(huán)的列表了手报。具體方法及細節(jié)見 demo 點我下載

學(xué)習(xí)參考資料:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蚯舱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子掩蛤,更是在濱河造成了極大的恐慌枉昏,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揍鸟,死亡現(xiàn)場離奇詭異兄裂,居然都是意外死亡,警方通過查閱死者的電腦和手機蜈亩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門懦窘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人稚配,你說我怎么就攤上這事畅涂。” “怎么了道川?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵午衰,是天一觀的道長立宜。 經(jīng)常有香客問我,道長臊岸,這世上最難降的妖魔是什么橙数? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮帅戒,結(jié)果婚禮上灯帮,老公的妹妹穿的比我還像新娘。我一直安慰自己逻住,他們只是感情好钟哥,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著瞎访,像睡著了一般腻贰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扒秸,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天播演,我揣著相機與錄音,去河邊找鬼伴奥。 笑死写烤,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的渔伯。 我是一名探鬼主播顶霞,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼锣吼!你這毒婦竟也來了选浑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤玄叠,失蹤者是張志新(化名)和其女友劉穎古徒,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體读恃,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡隧膘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了寺惫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疹吃。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖西雀,靈堂內(nèi)的尸體忽然破棺而出萨驶,到底是詐尸還是另有隱情,我是刑警寧澤艇肴,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布腔呜,位于F島的核電站叁温,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏核畴。R本人自食惡果不足惜膝但,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谤草。 院中可真熱鬧跟束,春花似錦、人聲如沸丑孩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嚎杨。三九已至,卻和暖如春氧腰,著一層夾襖步出監(jiān)牢的瞬間枫浙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工古拴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留箩帚,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓黄痪,卻偏偏與公主長得像紧帕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子桅打,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉是嗜,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,715評論 0 9
  • 國家電網(wǎng)公司企業(yè)標準(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,970評論 6 13
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)挺尾,斷路器鹅搪,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,558評論 33 466