首页 > 代码库 > 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(); }
这些可接受的文件类型集,包括:
FileType | 对应Id | 实际接受的文件后缀(acceptsFile) | mimeTypes |
FileTypeFB2 | fb2 | .fb2、.fb2.zip | application/x-fictionbook、application/x-fictionbook+xml、application/fb2+xml、text/fb2+xml、application/fb2+zip |
FileTypeEpub | ePub | epub、oebzip、opf | application/epub+zip、application/epub |
FileTypeMobipocket | Mobipocket | pdb、prc、mobi、azw3 | application/x-mobipocket-ebook |
FileTypeHtml | HTML | html、htm | text/html、application/html、application/html+htm |
FileTypeDjVu | DjVu | djvu、djv | image/vnd.djvu、image/x-djvu、application/djvu |
SimpleFileType | plain text | txt | text/plain、application/txt |
SimpleFileType | RTF | rtf | application/rtf、text/rtf |
SimpleFileType | application/pdf | ||
SimpleFileType | ZIP archive | zip | application/zip |
SimpleFileType | MS Word document | doc | application/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查看)将于FormatPlugin的myFileType进行匹配,匹配上了边返回对应的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();
myPlugins以FormatPlugin.Type为Key存储了对应FormatPlugin.Type的所有FormatPlugin。
FormatPlugin.Type的所有类型:FormatPlugin -> enum Type:
public enum Type { ANY, JAVA, NATIVE, EXTERNAL; };
某FormatPlugin子类 | 该类的myFileType | 其对应父类 | 该类的Type |
BuiltinFormatPlugin(abstract) | FormatPlugin(abstract) | ||
JavaFormatPlugin(abstract) | BuiltinFormatPlugin(abstract) | Type.JAVA | |
NativeFormatPlugin | BuiltinFormatPlugin(abstract) | Type.NATIVE | |
FB2NativePlugin | fb2 | NativeFormatPlugin | Type.NATIVE |
OEBNativePlugin | ePub | NativeFormatPlugin | Type.NATIVE |
MobipocketPlugin | Mobipocket | JavaFormatPlugin(abstract) | Type.JAVA |
ExternalFormatPlugin(abstract) | FormatPlugin(abstract) | Type.EXTERNAL | |
DjVuPlugin | DjVu | ExternalFormatPlugin(abstract) | Type.EXTERNAL |
PDFPlugin | ExternalFormatPlugin(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?
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。