最近研究了一下Android上pdf閱讀應(yīng)用和純文本閱讀應(yīng)用的相關(guān)東西。
先說pdf閱讀器,這個網(wǎng)上開源的東西比較多,解析pdf都是用的現(xiàn)成的庫,這種庫有很多,有java實現(xiàn)的,有c實現(xiàn)的。一搜一大堆,看過能有七 八個開源的pdf閱讀器,java實現(xiàn)的都巨慢無比,全都舍棄,c實現(xiàn)的速度還可以,看到用的最多的c庫是mupdf,主要是通過jni調(diào)用。但是要優(yōu)化 好那是相當(dāng)不容易了。另外,這些庫都相對比較大。
我參看了很多Market上的pdf閱讀應(yīng)用,感覺Adobe Reader做的帥呆了,以前沒覺得帥,主要是要研究優(yōu)化,看到了很多以前沒看到的技術(shù)上的細(xì)節(jié),Adobe Reader優(yōu)化做的相當(dāng)好。
其實pdf渲染機(jī)制,和瀏覽器渲染網(wǎng)頁有很多相似的東西,一些優(yōu)化手段是相同的,Android 4.0上的瀏覽器看著特別明顯。
那么就說下pdf渲染機(jī)制,我看到的大部分實現(xiàn),其實最終渲染的是一張一張圖片(Adobe Reader還可以選擇文字,添加書簽,這簡直酷爆了,不知道怎么做的)。過程是,
先定位視口對于文檔的相對位置,然后根據(jù)pdf解析庫,得到相應(yīng)位置,相應(yīng)縮放比例的pdf的位圖,然后再把這個位圖用canvas繪制到屏幕上。這是最簡單的渲染機(jī)制,復(fù)雜的地方在于,頁的切換和頁面的放大縮小。
我們知道,由于手機(jī)設(shè)備內(nèi)存小,一個Android應(yīng)用只有很小的堆棧內(nèi)存分配,如果你不做任何處理,只是翻一頁生成一個圖片,放大縮小重新生成一 個圖片,那么很快就會oom,內(nèi)存溢出。這點可以看出,pdf的渲染機(jī)制,其實轉(zhuǎn)化成了很多圖片切換縮放的優(yōu)化處理。所以如何回收內(nèi)存,何時回收內(nèi)存是個 大問題。
我的目標(biāo)交互是,頁連續(xù)豎直緊挨排列,然后豎直滑動瀏覽??梢远帱c縮放大小,放大后,可以左右滑動位置。(類似于Adobe Reader)
當(dāng)用戶上下滑動到某個位置的時候,通過jni調(diào)用生成圖片(有個延遲),然后該可視范圍內(nèi)的圖片生成重繪出來,當(dāng)再次滑動到了新的位置時,為了防止 內(nèi)存溢出,應(yīng)當(dāng)回收之前的圖片,但是這樣的問題就是,當(dāng)用戶在回到剛才的位置時,由于圖片回收了,所以顯示的是空白,這樣體驗很不好。通關(guān)觀察一些應(yīng)用和 開源實現(xiàn),我總結(jié)發(fā)現(xiàn),滑動回剛才的位置時應(yīng)該首先加載了原來位置處的縮略圖(之前要緩存),然后再加載正確比例的圖片,這樣,視覺上看起來就好很多,可 以大概看到那個位置的東西,這樣的感覺就是很快。
然后是縮放,放大或者縮小都需要通過jni重新生成這確比例的位圖,然后重新渲染,這樣也存在那個問題。其實渲染的過程仔細(xì)看,可以看出渲染應(yīng)該是 分塊渲染的,不是整屏的位置都一起渲染一個大圖,而是等分成按比例的若干個塊,然后一個塊一個塊的分塊加載。這樣的話,放大好弄一點,放大時,以放大中心 位置所在的那個塊放大,顯示縮放原始的這樣位圖,所以當(dāng)發(fā)大后會有點虛,然后放大結(jié)束后才真正渲染正確比例的位圖。然后回收周圍那些看不到的位圖,這樣問 題就來了,當(dāng)再縮小時,周邊的圖由于被回收了,所以變成了空白,這點Android4.0原生瀏覽器特別明顯,其實還是可以優(yōu)化的,Adobe Reader是這樣做的,周圍的圖片緩存了縮略圖,當(dāng)縮小的時候,周圍的圖會迅速渲染上縮略圖,看著有點模糊,但是比起空白好多了,所以這樣,效果就相當(dāng) 贊了。
總結(jié)一下就是,分塊加載,緩存縮略圖,動態(tài)生成真實比例的位圖,及時回收位圖。這里面其實涉及到大量細(xì)節(jié),實現(xiàn)起來相當(dāng)復(fù)雜。
另外,基于c的開源實現(xiàn)的pdf閱讀器,基本上都用了mupdf這個庫,并且mupdf這個庫自帶了一個Android的簡單demo,沒有做任何 優(yōu)化處理,只是一頁一頁的顯示。另外,Android 4.0的原生瀏覽器很順滑,可以看出做了很多優(yōu)化,當(dāng)然這里面緩存,分塊,回收,生成的時機(jī)相當(dāng)重要,也很復(fù)雜,是最大的難點。
一些相關(guān)連接:
一些開源的pdf查看器:(還有一些,鏈接已經(jīng)不記得了)
http://code.google.com/p/apv/
http://code.google.com/p/droidreader/
http://code.google.com/p/vudroid/
http://code.google.com/p/ebookdroid/ (優(yōu)化的最好的,實現(xiàn)了我文中所說的大部分優(yōu)化)





