小說閱讀器類型分析與源碼展示

作爲一個資深小說迷和一個優秀的程序猿的我,最近一年都在研究小說閱讀器,終於......。

小說類型大致分三種:資源閱讀型,本地文件閱讀型,網絡綜合型。

步步遞進,我的學習過程也是這樣的(文章最後有彩蛋!)

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

 

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