首页 > 代码库 > FBReader代码分析:创建BookModel时,如何根据Book来得到对应的FormatPlugin?

FBReader代码分析:创建BookModel时,如何根据Book来得到对应的FormatPlugin?

本篇文章暂时只是本人看代码过程中备忘的记录,未详细的整理,条理不太清晰。

 

BookModel -> createModel(Book book);

Book -> getPlugin() -> getPlugin(ZLFile) -> 实际由PluginCollection类获取:

PluginCollection -> getPlugin(ZLFile) -> getPlugin(file, FormatPlugin.Type.ANY)

    public FormatPlugin getPlugin(ZLFile file, FormatPlugin.Type formatType) {        final FileType fileType = FileTypeCollection.Instance.typeForFile(file);        final FormatPlugin plugin = getPlugin(fileType, formatType);        if (plugin != null && plugin.type() == FormatPlugin.Type.EXTERNAL) {            return file == file.getPhysicalFile() ? plugin : null;        }        return plugin;    }

FileTypeCollection类初始化了所有可接受的文件类型:FileTypeCollection

     /**     * 以FileType的Id为Key,FileType为值存储下来     */    private final TreeMap<String, FileType>    myTypes        = new TreeMap<String, FileType>();    private FileTypeCollection()    {        addType(new FileTypeFB2());        addType(new FileTypeEpub());        addType(new FileTypeMobipocket());        addType(new FileTypeHtml());        addType(new SimpleFileType("plain text", "txt", MimeType.TYPES_TXT));        addType(new SimpleFileType("RTF", "rtf", MimeType.TYPES_RTF));        addType(new SimpleFileType("PDF", "pdf", MimeType.TYPES_PDF));        addType(new FileTypeDjVu());        addType(new SimpleFileType("ZIP archive", "zip", Collections.singletonList(MimeType.APP_ZIP)));        addType(new SimpleFileType("MS Word document", "doc", MimeType.TYPES_DOC));    }    private void addType(FileType type)    {        myTypes.put(type.Id.toLowerCase(), type);    }    public Collection<FileType> types()    {        return myTypes.values();    }    

这些可接受的文件类型集,包括:

表1:支持的FileType
FileType对应Id实际接受的文件后缀(acceptsFile)mimeTypes
FileTypeFB2fb2.fb2、.fb2.zipapplication/x-fictionbook、application/x-fictionbook+xml、application/fb2+xml、text/fb2+xml、application/fb2+zip
FileTypeEpubePubepub、oebzip、opfapplication/epub+zip、application/epub
FileTypeMobipocketMobipocketpdb、prc、mobi、azw3application/x-mobipocket-ebook
FileTypeHtmlHTMLhtml、htmtext/html、application/html、application/html+htm
FileTypeDjVuDjVudjvu、djvimage/vnd.djvu、image/x-djvu、application/djvu
SimpleFileTypeplain texttxttext/plain、application/txt
SimpleFileTypeRTFrtfapplication/rtf、text/rtf
SimpleFileTypePDFpdfapplication/pdf
SimpleFileTypeZIP archivezipapplication/zip
SimpleFileTypeMS Word documentdocapplication/msword、application/doc

可以根据传入的ZLFile得到该ZLFile所被支持的FileType对象:FileTypeCollection -> typeForFile(ZLFile file)

   public FileType typeForFile(ZLFile file)    {        for (FileType type : types()) {            if (type.acceptsFile(file)) {                return type;            }        }        return null;    }

实际获取FormatPlugin的方法PluginCollection -> getPlugin(FileType fileType, FormatPlugin.Type formatType)

  public FormatPlugin getPlugin(FileType fileType, FormatPlugin.Type formatType) {        if (fileType == null || formatType == null) {            return null;        }        switch (formatType) {            case ANY:            {                  FormatPlugin p = getPlugin(fileType, FormatPlugin.Type.NATIVE);// 优先获取Native的FormatPlugin
                if (p == null) {// 加载不到时才加载Java的FormatPlugin
                    p = getPlugin(fileType, FormatPlugin.Type.JAVA);
                }
                if (p == null) {// 再加载不到时,加载扩展的FormatPlugin
                    p = getPlugin(fileType, FormatPlugin.Type.EXTERNAL);
                }
                return p; }
default: { final List<FormatPlugin> list = myPlugins.get(formatType); if (list == null) { return null; } for (FormatPlugin p : list) {
            // p.supportedFileType()实际返回的是初始化FormatPlugin时传入的myFileType(从表2查看);
            // FileType的Id值(从表1查看)将于FormatPluginmyFileType进行匹配,匹配上了边返回对应的FormatPlugin
if (fileType.Id.equalsIgnoreCase(p.supportedFileType())) { return p; } } return null; } } }

1.首先默认进入了ANY,递归再次进入,携带的formatType为FormatPlugin.Type.NATIVE
,然后进入的是default。

2.然后得由这个formatType去得到List<FormatPlugin>。现在需要知道myPlugins是怎么来初始化的?
// ======================= 以下代码便是myPlugins的初始化过程=======================
private final Map<FormatPlugin.Type,List<FormatPlugin>> myPlugins =
        new HashMap<FormatPlugin.Type,List<FormatPlugin>>();


public
static PluginCollection Instance() { if (ourInstance == null) {
       // 这里初始化所有支持的FormatPlugin实例
       // 1.MobipocketPlugin -> FormatPlugin.Type.Java
       // 2.DjVuPlugin -> FormatPlugin.Type.EXTERNAL
       // 3.PDFPlugin -> FormatPlugin.Type.EXTERNAL
       ourInstance
= new PluginCollection();
       
// This code can not be moved to constructor because nativePlugins() is a native method for (NativeFormatPlugin p : ourInstance.nativePlugins()) { ourInstance.addPlugin(p); System.err.println("native plugin: " + p); } } return ourInstance; }private PluginCollection() { addPlugin(new MobipocketPlugin()); if (Build.VERSION.SDK_INT >= 8) { addPlugin(new DjVuPlugin()); addPlugin(new PDFPlugin()); } }private void addPlugin(FormatPlugin plugin) { final FormatPlugin.Type type = plugin.type(); List<FormatPlugin> list = myPlugins.get(type); if (list == null) { list = new ArrayList<FormatPlugin>(); myPlugins.put(type, list); } list.add(plugin); }

private void NativeFormatPlugin[] nativePlugins();
myPluginsFormatPlugin.Type为Key存储了对应FormatPlugin.Type的所有FormatPlugin。

FormatPlugin.Type的所有类型:FormatPlugin -> enum Type:
public enum Type {        ANY,        JAVA,        NATIVE,        EXTERNAL;    };
表2:支持的FormatPlugin
某FormatPlugin子类该类的myFileType其对应父类该类的Type
BuiltinFormatPlugin(abstract) FormatPlugin(abstract) 
JavaFormatPlugin(abstract) BuiltinFormatPlugin(abstract)Type.JAVA
NativeFormatPlugin BuiltinFormatPlugin(abstract)Type.NATIVE
FB2NativePlugin fb2NativeFormatPluginType.NATIVE
OEBNativePlugin ePubNativeFormatPluginType.NATIVE
MobipocketPlugin MobipocketJavaFormatPlugin(abstract)Type.JAVA
ExternalFormatPlugin(abstract) FormatPlugin(abstract)Type.EXTERNAL
DjVuPlugin DjVuExternalFormatPlugin(abstract)Type.EXTERNAL
PDFPlugin PDFExternalFormatPlugin(abstract)Type.EXTERNAL

打开某一个epub资源 example.epub ,断点进入时,下面是所有FileType的值:

{djvu=org.geometerplus.zlibrary.core.filetypes.FileTypeDjVu@52ddbe84, epub=org.geometerplus.zlibrary.core.filetypes.FileTypeEpub@52dda188, fb2=org.geometerplus.zlibrary.core.filetypes.FileTypeFB2@52dd9fd8, html=org.geometerplus.zlibrary.core.filetypes.FileTypeHtml@52dda6d0, mobipocket=org.geometerplus.zlibrary.core.filetypes.FileTypeMobipocket@52dda4e8, ms word document=SimpleFileType [MS Word document], pdf=SimpleFileType [PDF], plain text=SimpleFileType [plain text], rtf=SimpleFileType [RTF], zip archive=SimpleFileType [ZIP archive]}

下面是所有FormatPlugin的值:

技术分享

可以看出共有六种类型的FormatPlugin当前被支持了。
因此,上面的example.epub资源,其对应的FileType是epub=org.geometerplus.zlibrary.core.filetypes.FileTypeEpub[ePub],FormatPlugin是OEBNativePlugin[ePub]。



 

 

 

 

 

 
 
 
 

FBReader代码分析:创建BookModel时,如何根据Book来得到对应的FormatPlugin?