Reader電子書閱讀器優化實戰(一)

  我今天主要說的電子書閱讀器源碼如下:https://github.com/GGGHub/Reader。首先要感謝原作者的分享,有一個完整的,能運行的電子書閱讀器demo。讓我們爲作者的這種開源精神點贊
  雖然這個電子書閱讀器demo是衆多開源中相對比較完善的一個,但是也已經有兩年沒有更新了。也存在了一些問題急需要解決。我把存在的問題梳理如下:

  • 沒有重用機制,內存開銷大,滑動起來反應特別慢

  • 某些情況下存在閃退,崩潰現象

  • 每次打開電子書都需要解壓,解壓時間比較長

當然了還有一些細節的小問題,我這裏就不再一一的列舉了。

沒有重用機制,內存開銷大,滑動起來反應特別慢

沒有重用機制,對於一個電子書閱讀器來說應該是最大的一個軟肋,因爲用戶看小說的時候事件比較長,在這段連續的時間內,用戶已經連續翻頁,劃過了很多頁面,如果沒有重用機制的話,就會造成內存爆增,app出現卡頓現象,如果滑動比較快的話,內存不夠,app就會被殺死造成閃退。
解決思路:我這邊從時間成本上考慮,直接使用UIcollectionView來進行復用。
同時每一個頁面就是一個單獨的cell。關鍵代碼如下:

#pragma mark - - - - UIScrollViewDelegate - - - -
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{

    NSInteger index = scrollView.contentOffset.x/ scrollView.bounds.size.width;
    if (index == self.cellCount-1 || index == 0) {
        [self scrollToOriginCell];
    }
}

#pragma mark - - - - UICollectionViewDataSource - - - -
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath*)indexPath {

    JKPageCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:[JKPageCollectionCell CellIndentifier] forIndexPath:indexPath];
    [self refreshTheReadModelWithIndex:indexPath.item];
    NSInteger count = indexPath.item - self.middleIndex;
    if (count >= [self eyeProductCellCount]) {
        self.eyeProductView.backgroundColor = [LSYReadConfig shareInstance].theme;
        self.eyeProductView.hidden = NO;
    }

    self.lastPageIndex = indexPath.item;
    [cell updateViewWithModel:self.model];
    return cell;
}

我這邊cellCount設置的比較大是1000.方便用戶體驗,用戶滑動到500頁的時候,會給用戶彈出一個護眼提醒。同時將cell滾動到最初的頁面,給用戶一個可以無限滑動的假象。哈哈
但是在實際的操作中卻發現,左右滑動切換的時候出現了頁面數據刷新的不準確的情況。經過排查發現iOS 10 以後,collectionView優化造成的,我這邊處理代碼如下:

if (@available(iOS 10.0,*)) {
       self.collectionView.prefetchingEnabled = NO;
    }

某些情況下存在閃退,崩潰現象

存在閃退,崩潰現象,剛開始優化之前還是比較頻繁的,統計下來主要體現在兩個方面,第一就是沒有重用機制,內存緊張造成的app閃退。第二就是frameRef對象無法歸檔造成的,繪製是,內容確實造成的crash。第一種情況通過重用已經能夠得到解決,第二種情況我這邊主要是在對epub格式的文件處理時,考慮到framRef的對象無法歸檔,我這邊重新進行了一次的解壓,獲取相關的chapters信息,具體代碼如下:

+(id)getLocalModelWithURL:(NSURL *)url
{
    NSString *key = [url.path lastPathComponent];
    NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:key];
    if (!data) {
        if ([[key pathExtension] isEqualToString:@"txt"]) {
            LSYReadModel *model = [[LSYReadModel alloc] initWithContent:[LSYReadUtilites encodeWithURL:url]];
            model.resource = url;
            [LSYReadModel updateLocalModel:model url:url];
            return model;
        }
        else if ([[key pathExtension] isEqualToString:@"epub"]){
            LSYReadModel *model = [[LSYReadModel alloc] initWithePub:url.path];
            model.resource = url;
            [LSYReadModel updateLocalModel:model url:url];
            return model;
        }
        else{
            @throw [NSException exceptionWithName:@"FileException" reason:@"文件格式錯誤" userInfo:nil];
        }

    }
    NSKeyedUnarchiver *unarchive = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
    //主線程操作
    LSYReadModel *model = [unarchive decodeObjectForKey:key];
    if ([[key pathExtension] isEqualToString:@"epub"]){
       model.chapters = [LSYReadUtilites ePubFileHandle:url.path];//重新從path下解析獲取epubchapter的內容。
    }

    model.record.chapterModel = model.chapters.firstObject;
    return model;
}

每次打開電子書都需要解壓,解壓時間比較長

  針對這一種情況,我個人覺得, 完全沒有必要每次都解壓,只需一次解壓,然後保存解壓後的文件,然後每次從指定的文件夾打開就OK了,但是有由於存在電子書名字相同的情況,可能會出現bug,針對這一種情況。我這邊的解決方案是在電子書下載到app內的時候,自動的在電子書名字後面通過特殊分隔符號,添加一個時間戳,來進行標記,這樣可以很好的解決電子書重名的問題。
當然了,上面的解決方案只是自己在開發過程中,自己的個人觀點,可能不是特別的完美,歡迎大家的批評指正。如果大家對電子書開發感興趣的話,可以用QQ掃描下方的二維碼
這裏寫圖片描述

更多優質文章,可以微信掃碼關注:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章