小说阅读器类型分析与源码展示

作为一个资深小说迷和一个优秀的程序猿的我,最近一年都在研究小说阅读器,终于......。

小说类型大致分三种:资源阅读型,本地文件阅读型,网络综合型。

步步递进,我的学习过程也是这样的(文章最后有彩蛋!)

1.首先资源阅读型,就是把一整部小说放进Asset,然后通过context.getAssets(),获取书本

/**
 * package: com.example.luoyangcomputer.localbook.modelbook
 * created by luoyang
 */
public class BookLab {
    public static final String TEXT = "text";
    public static final String IMAGE = "image";
    private static BookLab sBookLab;

    private AssetManager mAssetManager;
    private List<Book> mBookList;
    //assets中的文件名清单
    private String[] mAssetsImageList;
    private String[] mAssetsTextList;


    private BookLab(Context context) {
        mAssetManager = context.getAssets();
        loadAssetsFiles();
    }


    public static BookLab newInstance(Context context) {
        if (sBookLab == null) {
            sBookLab = new BookLab(context);
        }
        return sBookLab;
    }

    //加载assets中的文件
    private void loadAssetsFiles() {
        mBookList = new ArrayList<>();
        //获取image、text中的文件名清单
        try {
            mAssetsImageList = mAssetManager.list(IMAGE);
            mAssetsTextList = mAssetManager.list(TEXT);
        } catch (IOException e) {
            e.printStackTrace();
        }


        for (int i = 0; i < mAssetsTextList.length; i++) {
            //获取书名
            String[] nameSplit = mAssetsTextList[i].split("_");
            String nameSecond = nameSplit[nameSplit.length - 1];
            String bookTitle = nameSecond.replace(".txt", "");

            //获取封面
            String imagePath = IMAGE + "/" + mAssetsImageList[i];
            Bitmap bookCover = loadImage(imagePath);

            //获取文本
            String textPath = TEXT + "/" + mAssetsTextList[i];
            String bodyText = loadText(textPath);


            Book book = new Book(bookTitle, bookCover, bodyText);
            mBookList.add(book);

        }

    }


    //从assets中读取文本
    private String loadText(String path) {
        InputStream in = null;
        BufferedReader reader = null;
        StringBuilder stringBuilder = new StringBuilder();

        try {
            in = mAssetManager.open(path);
            reader = new BufferedReader(new InputStreamReader(in));

            String line = "";
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return stringBuilder.toString();

    }

    //从assets中读取图片
    private Bitmap loadImage(String path) {
        Bitmap image = null;
        InputStream in = null;
        try {
            in = mAssetManager.open(path);
            image = BitmapFactory.decodeStream(in);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return image;
    }

    public List<Book> getBookList() {
        return mBookList;
    }
}

2,本地文件型获取方式,获取本地小说文件 ,这边是得到txt文件

public class FileUtils {

    /**
     * 获取文件编码
     * @param fileName
     * @return
     * @throws IOException
     */
    public static String getCharset(String fileName) throws IOException{
        String charset;
        FileInputStream fis = new FileInputStream(fileName);
        byte[] buf = new byte[4096];
        // (1)
        UniversalDetector detector = new UniversalDetector(null);
        // (2)
        int nread;
        while ((nread = fis.read(buf)) > 0 && !detector.isDone()) {
            detector.handleData(buf, 0, nread);
        }
        // (3)
        detector.dataEnd();
        // (4)
        charset = detector.getDetectedCharset();
        // (5)
        detector.reset();
        return charset;
    }

    /**
     * 根据路径获取文件名
     * @param pathandname
     * @return
     */
    public static String getFileName(String pathandname){
        int start=pathandname.lastIndexOf("/");
        int end=pathandname.lastIndexOf(".");
        if(start!=-1 && end!=-1){
            return pathandname.substring(start+1,end);
        }else{
            return "";
        }

    }

    public static List<File> getSuffixFile(String filePath, String suffere){
        List<File> files = new ArrayList<>();
        File f = new File(filePath);
        return getSuffixFile(files,f,suffere);
    }

    /**
     * 读取sd卡上指定后缀的所有文件
     * @param files 返回的所有文件
     * @param f 路径(可传入sd卡路径)
     * @param suffere 后缀名称 比如 .gif
     * @return
     */
    public static  List<File> getSuffixFile(List<File> files, File f, final String suffere) {
        if (!f.exists()) {
            return null;
        }

        File[] subFiles = f.listFiles();
        for (File subFile : subFiles) {
            if (subFile.isHidden()){
                continue;
            }
            if(subFile.isDirectory()){
                getSuffixFile(files, subFile, suffere);
            }else if(subFile.getName().endsWith(suffere)){
                files.add(subFile);
            } else{
                //非指定目录文件 不做处理
            }
//            Log.e("filename",subFile.getName());
        }
        return files;
    }

}

3.网络型,Rxjava Retrofit 获取网络小说信息,Jsoup解析


    /**
     * 该网站搜索小说  s.php?ie=gbk&q=斗罗大陆
     */
    @Override
    public Observable<List<SearchBookBean>> searchBook(String content, int page) {
        return getRetrofitObject(TAG).create(WjduoApi.class).searchBook("gbk", content).flatMap(new Function<String, ObservableSource<List<SearchBookBean>>>() {
            @Override
            public ObservableSource<List<SearchBookBean>> apply(String s) throws Exception {
                return analySearchBook(s);
            }
        });
    }


    private ObservableSource<List<SearchBookBean>> analySearchBook(final String s) {
        return Observable.create(new ObservableOnSubscribe<List<SearchBookBean>>() {
            @Override
            public void subscribe(ObservableEmitter<List<SearchBookBean>> emitter) throws Exception {
                try {
                    Document doc = Jsoup.parse(s);
                    Elements booksE = doc.getElementsByClass("so_list bookcase").get(0).getElementsByClass("bookbox");
                    if (null != booksE && booksE.size() >= 1) {
                        List<SearchBookBean> books = new ArrayList<SearchBookBean>();
                        for (int i = 0; i < booksE.size(); i++) {
                            SearchBookBean item = new SearchBookBean();
                            Element booksEP10 = booksE.get(i).getElementsByClass("p10").get(0);
                            item.setTag(TAG);
                         
                            item.setCoverUrl(TAG + booksEP10.getElementsByClass("bookimg").get(0).getElementsByTag("a")
                                    .get(0).getElementsByTag("img").get(0).attr("src"));
                            item.setNoteUrl(TAG + booksEP10.getElementsByClass("bookimg").get(0).getElementsByTag("a")
                                    .get(0).attr("href"));
                            item.setName(booksEP10.getElementsByClass("bookinfo").get(0).getElementsByClass("bookname")
                                    .get(0).getElementsByTag("a").get(0).text());

                            String kind = booksEP10.getElementsByClass("bookinfo").get(0).getElementsByClass("cat").get(0).text();
                            kind = kind.replace("分类:", "");
                            item.setKind(kind);
                            String author = booksEP10.getElementsByClass("bookinfo").get(0).getElementsByClass("author").get(0).text();
                            author = author.replace(" ", "").replace("  ", "").replace("作者:", "");
                            item.setAuthor(author);

                            item.setLastChapter(booksEP10.getElementsByClass("bookinfo").get(0).getElementsByClass("update")
                                    .get(0).getElementsByTag("a").get(0).text());
                            item.setDesc(booksEP10.getElementsByClass("bookinfo").get(0).getElementsByTag("p").get(0).text());
                            books.add(item);
                        }
                        emitter.onNext(books);
                    } else {
                        emitter.onNext(new ArrayList<SearchBookBean>());
                    }

                } catch (Exception ex) {
                    ex.printStackTrace();
                    emitter.onNext(new ArrayList<SearchBookBean>());
                }
                emitter.onComplete();
            }
        });
    }

我这边主要记录一下,需要源码的我这边推个本地小说源码https://github.com/luoyangGZS/luoluotushu.git

我试着综合了三种类型的,写了一个程序猿自己Android免费小说阅读

安装包链接:https://pan.baidu.com/s/1ooGAhY_dBPwdPoVxSPCStw  提取码:g18k

一起学习交流!创建价值,乐在分享!

洛洛小说改进阅读体验唯一讨论群组:949762199

猜你喜欢

转载自blog.csdn.net/ly_xiamu/article/details/84326895