上一章中咱們介紹了用ZLTextPlainModel類裏的char數組存儲.xhtml文件中的文本信息以及標籤信息的流程。 html
本章中咱們將介紹從ZLTextPlainModel類裏的char數組中定位指定段落的流程。 數組
本章涉及的核心類是Processor類(ZLTextParagraphCursor類內部類)、EntryIteratorImpl類(ZLTextPlainModel類內部類) 函數
定位到指定段落須要兩個方法互相配合:ZLTextParagraphCursor類的cursor方法和ZLTextPage類的moveStartCursor方法 spa
ZLTextParagraphCursor類的cursor方法負責填充表明指定段落的ZLTextParagraphCursor類。在這個過程當中,char數組中表明指定段落的部分轉換成一個由ZLTextElement類組成的ArrayList。其中,段落中的文本信息會被轉換成ZLTextElement類的子類ZLTextWord,而段落中的標籤信息會被轉換成ZLTextElement類的子類ZLTextControlElement。 orm
ZLTextPage類的moveStartCursor方法負責定位到指定的段落。定位的過程主要是維護ZLTextPage類中的StartCursor屬性指向的ZLTextWordCursor類。ZLTextWordCursor類中的三個屬性myParagraphCursor、myElementIndex、myCharIndex結合起來就完成來了定位到指定段落的流程。這三個屬性中,myParagraphCursor屬性指向的就是表明指定段落的ZLTextParagraphCursor類。 htm
當定位流程完成以後,char數組中涉及當前段落的部分會被轉換成一個由ZLTextElement子類組成的ArrayList中。這個ArrayList存儲在ZLTextParagraphCursor類中的myElements屬性中。而同時,ZLTextParagraphCursor這個類又存儲在ZLTextPage類的StartCursor屬性中。 索引
PS:整個定位流程其實也能夠當作ZLTextElement子類 -> ZLTextParagraphCursor類myElements屬性 -> ZLTextPage類StartCursor屬性不斷上推的過程。 內存
下面咱們結合ZLTextView的setModel方法詳細介紹下調用這兩個方法定位到定段落的具體流程: get
cursor方法的第一個參數爲解析xhtml文件獲得的ZLTextPlainModel類(第七章中有詳細介紹),第二個參數爲當前要顯示的段落的索引(初始時這個索引爲0) it
接着cursor方法以一樣的參數調用了ZLTextParagraphCursor類的構造函數
ZLTextParagraphCursor類構造函數
ZLTextParagraphCursor類構造函數調用了本類的fill方法,這個方法首先調用了ZLTextPlainModel類的getParagraph方法,接着又調用了Processor類的fill方法
ZLTextPlainModel類的getParagraph方法:
這個方法的做用是初始化了一個ZLTextParagraphImpl類,並定義了這個類中的myModel屬性(指向ZLTextPlainModel類)與myIndex屬性(當前要顯示的段落的索引)
這個方法將最終完成將char數組中表明當前段落的部分轉換成一個元素爲ZLTextElement類的ArrayList的工做。
方法大體流程是:首先經過EntryIteratorImpl類的構造方法得到正在處理的段落具體在char數組的哪一個部分(67行)。而後,利用EntryIteratorImpl類next方法在char數組的這個部分裏面不斷讀取內容並進行操做(71行)。操做分爲針對文本信息(75行)和針對標籤信息(84行)兩種。線面在詳細描述着兩個方法。
這個構造方法的做用就是利用當前段落的索引從ZLTextPlainModel類的三個屬性指向的int數組中的當前段落在char數組的哪一部分中。
這三個屬性咱們已經在第七章中有介紹過了。
myStartEntryIndices屬性指向的int數組記錄了每一個段落具體在CachedCharStorage類內部的哪個char數組裏面;
myStartEntryOffsets屬性指向的int數組記錄了每一個段落從CachedCharStorage類內部char數組的哪一個位置開始;
myParagraphLengths屬性指向的int數組記錄每一個段落在CachedCharStorage類內部char數組中佔據多少長度;
這個方法會在char數組的表明當前段落的部分裏面不斷讀取內容並進行操做。
在讀取的過程當中首先會經過CachedCharStorage類的block方法獲取對應須要顯示的段落的char數組(125行),獲取對應的char數組以後,代碼就會利用不斷遞增的dataOffset變量,不斷讀取char數組中的內容。一旦代碼讀取到表明文本信息或標籤信息的標示,就會進入不一樣的流程。
PS:咱們曾在上一章中介紹過這兩種標示,當時咱們是這麼介紹的:「每次調用addControl方法都會加入ZLTextParagraph.Entry.CONTROL(3)這個常量,這個常量是一種標示。相似的標示還有常量ZLTextParagraph.Entry.TEXT(1),咱們會在下一章用到這兩種變量」。
CachedCharStorage類的block方法:
咱們在上一章中介紹CachedCharStorage類的時候,曾經說過「char數組的長度最長不會超過這個長度(65536),一旦超過這個長度,代碼就會新建一個char數組,同時舊的數組會被持久化以便之後再用。」因此當前在內存中的char數組不必定會包含須要顯示的數組,若是不包含須要顯示的數組就須要根據ZLTextWritablePlainModel類的myStartEntryIndices屬性找到對應的char數組。(這個屬性的具體介紹也能夠在上一章中找到)
獲取到包含須要顯示的段落的char數組後,代碼就會利用不斷遞增的dataOffset變量,不斷讀取char數組中的內容。一旦代碼讀取到表明文本信息或標籤信息的標示,就會進入不一樣的流程。
獲取到包含須要顯示的段落的char數組後,代碼就會利用不斷遞增的dataOffset變量,不斷讀取char數組中的內容。一旦代碼讀取到表明文本信息或標籤信息的標示,就會進入不一樣的流程。
遇到表明文本的ZLTextParagraph.Entry.TEXT標示的狀況:
這種狀況下,代碼會對分在這個標示以後的文本信息會進行兩部分處理,一部分處理在EntryIteratorImpl類next方法中進行,一部分在Processor類的fill方法中進行
在EntryIteratorImpl類next方法中,會賦值兩個EntryIteratorImpl類的兩個變量。myTextLength屬性記錄文本信息的長度,myTextData屬性存儲當前char數組的引用。最後還經過賦值dataOffset,在char數組中向前跳過了涉及這段文本信息的部分。
在Processor類fill方法會調用本類的processTextEntry方法
在processTextEntry方法中代碼利用一個for循環,一個一個讀取char數組中的元素,而後對每一個元素調用Processor類的addWord方法。請注意,調用addWord方法時的參數。
addWord方法會初始化一個ZLTextWord類,而後將這個類加入ZLTextParagraphCursor類myElements屬性指向的ArrayList
請注意對比下ZLTextWord類構造函數與調用addWord方法時的參數
遇到表明文本的ZLTextParagraph.Entry.CONTORL標示的狀況:
這種狀況下,代碼一樣也會對跟在這個標示以後的標籤信息會進行兩部分處理,一部分處理在EntryIteratorImpl類next方法中進行,一部分在Processor類的fill方法中進行
EntryIteratorImpl類next方法會賦值三個屬性,請尤爲注意下myControlIsStart這個屬性,咱們會在處理樣式的時候用到這個屬性。
Processor類的fill方法會初始化一個ZLTextWord類,而後將這個類加入ZLTextParagraphCursor類myElements屬性指向的ArrayList
當代碼從ZLTextParagraphCursor類 cursor方法返回是,咱們會獲得新建的ZLTextParagraphCursor類,這個類中的myElements屬性指向的ArrayList已經被填充了表明當前段落中文本信息的ZLTextWord類與標籤信息的ZLTextControlElement類。接着就會進入ZLTextPage類的moveStartCursor方法。
這個方法比較簡單,其實就是將經過ZLTextParagraphCursor類的cursor方法填充好的ZLTextParagraphCursor類,賦值給ZLTextPage類內的StartCursor屬性
同時,ZLTextPage類內的StartCursor屬性指向的ZLTextWordCursor類進行下設置
完成moveStartCursor方法後,咱們就完成「定位指定段落」的流程了。