博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FBReaderv1.8.2启动,阅读流程,及显示研究
阅读量:7239 次
发布时间:2019-06-29

本文共 11381 字,大约阅读时间需要 37 分钟。

一.在AndroidManifest.xml中找到

可以看到应用程序的入口为FBReaderApplication

找到FBReaderApplication的类,里面定义如下

public class FBReaderApplication extends ZLAndroidApplication {}

那么,我们只能看基类ZLAndroidApplication的实现

public abstract class ZLAndroidApplication extends Application {    public ZLAndroidApplicationWindow myMainWindow;    @Override    public void onCreate() {        super.onCreate();        new ZLSQLiteConfig(this);        new ZLAndroidImageManager();        new ZLAndroidLibrary(this);    }}

它的工作就是

1.初始化sqlite
2.初始化一个图片管理类
3.初始化一个应用程序信息获取的类,如亮度,分辨率,dpi等等

二 找到启动Activity,在AndroidManifest.xml中找到:

即启动Activity为FBReader

三 下面找出启动之后,书本怎么解析

在FBReader.java类中,找到onStart()函数

protected void onStart() {        super.onStart();        getCollection().bindToService(this, new Runnable() {            public void run() {                new Thread() {                    public void run() {                        openBook(getIntent(), getPostponedInitAction(), false);                        myFBReaderApp.getViewWidget().repaint();                    }                }.start();                myFBReaderApp.getViewWidget().repaint();            }        });        initPluginActions();     // 其他    }

函数中加粗部分,跟踪。。

private synchronized void openBook(Intent intent, Runnable action, boolean force) {        Log.i("FBReader" , "FBReader::openBook");        if (!force && myBook != null) {            return;        }     // 其他          myFBReaderApp.openBook(myBook, bookmark, action);    }

继续跟踪上面加粗的函数

public void openBook(final Book book, final Bookmark bookmark, final Runnable postAction) {        Log.i("FBReader" , "FBReaderApp::openBook");        if (book != null || Model == null) {            runWithMessage("loadingBook", new Runnable() {                public void run() {                    openBookInternal(book, bookmark, false);                    if (book != null) {                        book.addLabel(Book.READ_LABEL);                        Collection.saveBook(book, false);                    }                }            }, postAction);        }    }

继续

synchronized void openBookInternal(Book book, Bookmark bookmark, boolean force) {        Log.i("FBReader", "FBReaderApp::openBookInternal");        if (book == null) { // book为空,获取最近阅读中的第一本书            book = Collection.getRecentBook(0);            if (book == null || !book.File.exists()) { // 如果没有阅读历史或者第一个最近阅读的书籍不存在,则打开帮助文件                 book = Collection.getBookByFile(BookUtil.getHelpFile());            }            if (book == null) {                return;            }            book.addLabel(Book.READ_LABEL);            Collection.saveBook(book, false);        }        if (!force && Model != null && book.equals(Model.Book)) {            if (bookmark != null) {                gotoBookmark(bookmark);            }            return;        }        onViewChanged();        storePosition();        BookTextView.setModel(null);        FootnoteView.setModel(null);        clearTextCaches();        Model = null;        System.gc();        System.gc();        try {            Model = BookModel.createModel(book);            Collection.saveBook(book, false);            ZLTextHyphenator.Instance().load(book.getLanguage());            BookTextView.setModel(Model.getTextModel());            setBookmarkHighlightings(BookTextView, null);            BookTextView.gotoPosition(Collection.getStoredPosition(book.getId()));            if (bookmark == null) {                setView(BookTextView);            } else {                gotoBookmark(bookmark);            }            Collection.addBookToRecentList(book);            final StringBuilder title = new StringBuilder(book.getTitle());            if (!book.authors().isEmpty()) {                boolean first = true;                for (Author a : book.authors()) {                    title.append(first ? " (" : ", ");                    title.append(a.DisplayName);                    first = false;                }                title.append(")");            }            setTitle(title.toString());        } catch (BookReadingException e) {            processException(e);        }        getViewWidget().reset();        getViewWidget().repaint();    }

 createModel函数如下:

public static BookModel createModel(Book book) throws BookReadingException {        final FormatPlugin plugin = book.getPlugin(); // 根据book获取Plugin,需要知道怎么获取Plugin的可以跟踪进去看看        System.err.println("using plugin: " + plugin.supportedFileType() + "/" + plugin.type());        final BookModel model;        switch (plugin.type()) { // 根据Plugin类型,选择用底层的Model还是选择Java层的Model            case NATIVE:                model = new NativeBookModel(book);                break;            case JAVA:                model = new JavaBookModel(book);                break;            default:                throw new BookReadingException("unknownPluginType", plugin.type().toString(), null);        }        plugin.readModel(model); // 这里调用ReadModel        return model;    }

这里强调下,java层木有txt的Plugin,所以我选择一个epub文件来继续在java层跟踪具体实现。

@Override    public void readModel(BookModel model) throws BookReadingException {        Log.i("FBReader" , "OEBPlugin::readModel");        model.Book.File.setCached(true);        new OEBBookReader(model).readBook(getOpfFile(model.Book.File));    }

这里重头戏来了。

OEBBookReader.java中的readBook函数如下

void readBook(ZLFile file) throws BookReadingException {        Log.i("FBReader", " OEBBookReader::readBook:ZLFile fileName = " + file.getShortName());        myFilePrefix = MiscUtil.htmlDirectoryPrefix(file);      // 清理缓存之类        myIdToHref.clear();        myHtmlFileNames.clear();        myNCXTOCFileName = null;        myTourTOC.clear();        myGuideTOC.clear();        myState = READ_NONE;        try {            read(file); // 这里标记为第一步,以epub随遇而安为例子,这里打开的是/mnt/sdcard/Download/随遇而安.epub:tencent/content.opf        } catch (IOException e) {            throw new BookReadingException(e, file);        }        myModelReader.setMainTextModel();        myModelReader.pushKind(FBTextKind.REGULAR);        int count = 0;        for (String name : myHtmlFileNames) { // 所有章节对应的文件名            final ZLFile xhtmlFile = ZLFile.createFileByPath(myFilePrefix + name);            if (xhtmlFile == null || !xhtmlFile.exists()) {                continue;            }                        Log.i("FBReader", " xhtmlFile = " + xhtmlFile.getLongName());                        if (count++ == 0 && xhtmlFile.getPath().equals(myCoverFileName)) {                continue;            }            final XHTMLReader reader = new XHTMLReader(myModelReader, myFileNumbers);            final String referenceName = reader.getFileAlias(MiscUtil.archiveEntryName(xhtmlFile.getPath()));            myModelReader.addHyperlinkLabel(referenceName);            myTOCLabels.put(referenceName, myModelReader.Model.BookTextModel.getParagraphsNumber());            try {                reader.readFile(xhtmlFile, referenceName + '#'); // 这里定义为第二步,解析每个章节的内容,第二部最终还是会去调用parser.doIt();            } catch (IOException e) {                throw new BookReadingException(e, xhtmlFile);            }            myModelReader.insertEndOfSectionParagraph();        }        generateTOC();    }

 先跟踪第一步的代码

public void read(ZLFile file) throws IOException {        ZLXMLProcessor.read(this, file);    }
public static void read(ZLXMLReader xmlReader, ZLFile file) throws IOException {        read(xmlReader, file, 65536);// 一次性读取64K    }
public static void read(ZLXMLReader xmlReader, ZLFile file, int bufferSize) throws IOException {        InputStream stream = file.getInputStream(); // 这里打开文件读取数据流啊        try {            read(xmlReader, stream, bufferSize);        } finally {            try {                stream.close();            } catch (IOException e) {            }        }    }
public static void read(ZLXMLReader xmlReader, InputStream stream, int bufferSize) throws IOException {        ZLXMLParser parser = null;        try {            parser = new ZLXMLParser(xmlReader, stream, bufferSize);            xmlReader.startDocumentHandler();            parser.doIt();// 解析啊,这里就是读取xml文件的内容啊            xmlReader.endDocumentHandler();        } finally {            if (parser != null) {                parser.finish();            }        }    }

 到这里,第一步算是解析完成了

我们再看看第一步解析出来的数据到哪里去了

在ZLXMLParser中

void doIt() throws IOException {
case TEXT: while (true) { switch (buffer[++i]) { case '<': if (i > startPosition) { xmlReader.characterDataHandlerFinal(buffer, startPosition, i - startPosition); } state = LANGLE; break mainSwitchLabel; case '&': if (i > startPosition) { xmlReader.characterDataHandler(buffer, startPosition, i - startPosition); } savedState = TEXT; state = ENTITY_REF; startPosition = i + 1; break mainSwitchLabel; } } } } } }

看到加粗函数了没?

 跟踪进去啦!

public void characterDataHandlerFinal(char[] ch, int start, int length) {        characterDataHandler(ch, start, length);    }

在XHTMLReader中的characterDataHandler函数

public void characterDataHandler(char[] data, int start, int len) {            if (len > 0) {            if (myInsideBody && !myModelReader.paragraphIsOpen()) {                myModelReader.beginParagraph();            }            myModelReader.addData(data, start, len, false);        }    }

在BookReader中

public final void addData(char[] data, int offset, int length, boolean direct) {        if (!myTextParagraphExists || length == 0) {            return;        }        if (!myInsideTitle && !mySectionContainsRegularContents) {            while (length > 0 && Character.isWhitespace(data[offset])) {                --length;                ++offset;            }            if (length == 0) {                return;            }        }        myTextParagraphIsNonEmpty = true;        if (direct && myTextBufferLength == 0 && !myInsideTitle) {            myCurrentTextModel.addText(data, offset, length);        } else {            final int oldLength = myTextBufferLength;            final int newLength = oldLength + length;            if (myTextBuffer.length < newLength) {                myTextBuffer = ZLArrayUtils.createCopy(myTextBuffer, oldLength, newLength);            }            System.arraycopy(data, offset, myTextBuffer, oldLength, length);            myTextBufferLength = newLength;            if (myInsideTitle) {                addContentsData(myTextBuffer, oldLength, length);            }        }        if (!myInsideTitle) {            mySectionContainsRegularContents = true;        }    }

到此为止,解析出来的数据添加到BookReader的myCurrentTextModel中,或者是添加到缓存myContentsBuffer

 

转载于:https://www.cnblogs.com/deagle/articles/3262289.html

你可能感兴趣的文章
结构型模式之Adapter模式
查看>>
Silverlight Popup Bubble
查看>>
【转】在Ubuntu下编译Android源码并运行Emulator
查看>>
ASP.NET Web API 全局权限和异常处理
查看>>
从头来之【iOS及历史版本特性介绍】
查看>>
C语言——指针
查看>>
JobControl 的实现原理
查看>>
【leetcode】Rotate Image(middle)
查看>>
Android之listview运用(美团美食列表)
查看>>
【转】Mybatis/Ibatis,数据库操作的返回值
查看>>
iOS UITextView 输入内容实时更新cell的高度
查看>>
SQL删除重复数据方法
查看>>
Sql Server函数全解<一>字符串函数
查看>>
2015年第9本:别让猴子跳回背上
查看>>
动态设置表格[GridView]在编辑时 只读。
查看>>
ExtJS4 自己定义基于配置的高级查询1
查看>>
C#调用杀毒软件MSE扫描指定目录或文件
查看>>
SQL中declare申明变量
查看>>
datatable 的ajax修改参数,post可以传参处理
查看>>
远程控制编写之屏幕传输 MFC实现 屏幕截图 发送bmp数据 显示bmp图像
查看>>