Bug頻出的Spannable,如何作一個Markdown解析器?

前言

以前寫了一個沸點說被排了一個任務寫一個Markdown解析器,如今分享一下全程的思路好了。git

Github傳送門

Markdown解析器概論

先來看一張圖片,清醒一下咱們的腦瓜子好了github

裏面有不少要實現的功能,固然我尚未實現出來。畢竟我週一至週三一直在上課,如今才抽出空來寫代碼了。先進行一個語法劃分,在圖中我也已經寫到了。可是一樣注意,並無表格的顯示,確實尚未思路。bash

要用什麼樣的方式去進行一個Markdown解析的實現呢?markdown

這是一個很是值得思考的問題了,我看了很多的源碼,給出的方案都是基本統一 —— HTML。但顯然對Android而言不是一個很是好的方案了,因此縱觀一下整個Android中的各個方案,好比說TextView複合,確實可以實現,可是從一個性能角度上來講,若是一個標題一個TextView,一個正文又是TextView。那麼以下所示的Markdown文本他有多少個TextView進行復合呢?post

# 大標題
## 中標題
### 小標題
這是一個測試案例
複製代碼

顯然是4個沒跑了,可是咱們能不能簡化呢?性能

上面咱們說了HTML,顯然這是一個解決方案,可是沒有其餘的方案了嗎?顯然是有的,Android內部其餘提供了一個叫作Spannable的玩意兒,能夠高效的實現一個不一樣樣式文本的拼接,但一樣的有一點很不幸,這玩意兒沒有這麼好用其實。看了網上不少不少的教程,爲了學習而學習,而不是爲了實戰而學習的文章大有所在,爲何這麼說呢?學習

其實你去進行嘗試就會發現,若是你複用一樣的Span,前者就會失效;或者說你下標沒有把控會直接影響到後續的Span,可是這在別人的教程卻徹底沒有說起到,固然我還在試錯的階段,還有什麼問題歡迎反饋。測試

Markdown解析器的構思

Markdown解析器進行分析的時候,咱們應該對整個的文本作一個瞭解,就拿掘金的Markdown解析器來講好了。何時會成爲一行,和簡書的Markdown語法器存在一點不同的地方,若是說你要完成一個正文的分行,你須要兩個回車,而簡書只須要一個,其餘的二者基本保持一致。spa

爲了方便起見,咱們按照簡書的方案來好了。下面爲各位羅列一下總體的思路是怎麼樣的:3d

  1. 以行讀入。 這是一個標準,爲何這麼說呢,你能夠發現,你每次進行完一個行時,就須要敲一次回車鍵不是。因此以行讀入,天然而然的爲你進行了一個語法的區分。
  2. 行內解析 前面咱們講了行讀入,可是爲何還要行解析呢?解析什麼?很簡單,看看咱們上面作過的一個思惟導圖。一個行內可能會出現各類語法,好比說粗體,斜體,粗體加斜體,正常文字等等等等。。。因此行內解析很是之重要。
  3. 行間解析 行間解析的做用是什麼?其實就是爲了區分咱們的一個有序和無序列表,還有引言了,固然我以爲表格也一樣的能夠加入和這個行列中來。

怎麼樣去組合這些解析的數據。很簡單的方案就是經過兩個鏈表的組合來完成,一個用於存儲數據,一個用於存儲數據類型。

經過上述的思路,咱們先可以對Markdown語法作一個總體的分析。下面給出一個分析以後的結果

在途中顯示的結果有一、二、三、四、5.....等等數字,其實對應就是一個個不同的標籤,經過串在一塊兒,然咱們再進行總體的數據顯示。可是可以看到我仍是使用了一個 HTML的標籤,主要是由於還沒想出行內的格式轉化應該怎麼樣去作,如今主要是爲了一個效果,後期會進行更正。

Spannable閃亮登場

先看看咱們會出現的Bug

你能明顯的看到 標題1標題2的樣式並不相同,那讓咱們看看測試 Markdown文件。

# 標題1
# 標題2
## 人員
### 人員
############# 人員
文字![123](222)`123`11**11*
> 123
> 123
1. 2
2. 4
+ 2
複製代碼

由於代碼塊還沒作就先不放了。

你能明顯的看到標題1標題2經過Markdown語法顯示出來的照理應該說是<h1>標籤這樣的形式,可是實際效果確實咱們也看到了不一樣,這就是Spannable他的一個Bug,固然解決方案也是有的。就是從新定義長度,你的Start要向前延伸。最方便的方案就是使用一個棧來保存了。

而後經過入棧的數量,判斷以前的重複數量有多少個,就能夠從新定義長度了。

可是要注意,上面說的是行間是須要這樣去進行解析的,而行內的操做並不能這樣亂來,你要先進行分析,再進行組合,否則總體就會產生巨大的混亂。而行內解析的方法就不太同樣了,我並無作性能過多的考慮,進行兩次循環操做,先進行一次總體的數據分析,再是對已經分析好的數據進行整合,這樣就會省去不少的麻煩事兒。剩下的主要就是一些樣式和邏輯判斷的問題了。

最後還有一個問題就是,關於連接點擊的問題,這是統一的問題,爲了解決Google早就已經給出了方案。

text.movementMethod = LinkMovementMethod.getInstance()
複製代碼

項目持續更新,但願一樣可以獲得你的Star。

以上就是個人學習成果,若是有什麼我沒有思考到的地方或是文章內存在錯誤,歡迎與我分享。


相關文章推薦:

實戰酷斃了的自定義View(三)

實戰酷斃了的自定義View(二)

實戰酷斃了的自定義View(一)

相關文章
相關標籤/搜索