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(一)

相关文章
相关标签/搜索