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扫描下方的二维码
这里写图片描述

更多优质文章,可以微信扫码关注:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/HHL110120/article/details/81561804