
網(wǎng)友的使用經(jīng)驗
簡友gton的LChart中的折線圖在項目中的簡單使用

正文前言
核心:面向?qū)ο?/strong>
面向?qū)ο筮@個名詞,對于我們廣大的程序員來說,應(yīng)該是再熟悉不過了。
多數(shù)人只是停留在熟悉名詞這個階段,
在遇到一些問題的時候,卻不知道采用面向?qū)ο蟮乃季S去解決它。
當(dāng)我們跳出老舊的思維枷鎖,很多問題也就迎刃而解了 :)
LChart的產(chǎn)生
我們在項目中,經(jīng)常使用圖表來展示數(shù)據(jù),這樣很形象直觀。在Android中,我們大多會使用如下常用的圖表庫:
- MPAndroidChart (展示豐富,性能好,但是使用較為麻煩,源碼難懂,定制起來很困難)
- HelloCharts(使用較為簡單,數(shù)據(jù)量較大的時候,性能差)
以上的圖表庫,都有著各自的優(yōu)缺點,項目對圖表要求不高的話,使用他們完全沒問題。但是要求高的話,這就麻煩了,最后的解決方法是自己重寫一個圖表 :(
既然項目的圖表要求高,那咱就自己寫個圖表庫唄:LChart就是這么產(chǎn)生的。
項目地址:https://github.com/linheimx/LChart
對于LChart,我是以面向?qū)ο蟮姆绞絹矸纸馑L制它的,整體來說思路清晰,易于使用。
也許LChart也不適應(yīng)于你的項目,但我想在這篇文章里面授之以漁,給你帶來一定的幫助。
LChart的組織結(jié)構(gòu)
面向圖譜中的對象
知道了一個東西由哪幾個部分組成,我們內(nèi)心對這個東西就有數(shù)了(不一定了如指掌,有了大概的輪廓也就可以啦)
我們先看一輛自行車的組成結(jié)構(gòu)(幫助我們尋找靈感)

從上圖,我們大致看出自行車有如下結(jié)構(gòu):
- 車輪子
- 坐墊
- 車把
對比自行車的結(jié)構(gòu),那我們的LChart由那幾部分組成呢?


從上面基本的折線圖,我們大致可以看出LChart由如下幾個部分組成:
- 軸線
- 高亮
- 折線
限于篇幅,我只直觀的展示LChart的中3個主要部分,總體上有如下幾個部分:

針對以上部分,在我們的代碼中,對應(yīng)為相關(guān)的類,這些類封裝了相關(guān)的信息:

有了這幾個對象信息,我們就該考慮繪圖了。
根據(jù)對象信息進(jìn)行繪制
LChart是一個自定義View,通過view中的Canvas來進(jìn)行繪制。
我們設(shè)計了幾個render來負(fù)責(zé)繪制LChart的幾個關(guān)鍵部分。
每個render都有著自己的職責(zé),它向我們封裝的對象 Axis,Line等來獲取信息,進(jìn)行各種各樣的繪制。

render的體系結(jié)構(gòu)如下:

LChart的映射:將數(shù)據(jù)展現(xiàn)到屏幕上
我們的目的是將數(shù)據(jù)繪制到屏幕上,那么數(shù)據(jù)和屏幕之間有什么關(guān)系呢?
- 數(shù)據(jù)是有范圍的:表現(xiàn)在x方向上范圍和y方向上的范圍。
- 明確繪制圖譜在手機(jī)屏幕上的的區(qū)域
二者之間的聯(lián)系是等比例關(guān)系,如下圖:

在LChart中,我用MappingManager來維護(hù)管理這個關(guān)系:

考慮到對圖譜的縮放,移動,現(xiàn)將數(shù)據(jù)視圖具體分為:
RectD _maxViewPort; //當(dāng)前可見的數(shù)據(jù)范圍
RectD _currentViewPort; //最大的數(shù)據(jù)范圍
MappingManager中具體的數(shù)值與像素轉(zhuǎn)換的代碼:

知道了數(shù)據(jù)與手機(jī)屏幕中繪圖區(qū)域的關(guān)系。
隨便給你一個數(shù)據(jù),根據(jù)這個關(guān)系,你就可以知道這個點在屏幕中的位置了,知道了位置,你用canvas就隨便畫嘍。
LChart的性能優(yōu)化
1. 減少內(nèi)存分配
考慮到onDraw()的頻繁調(diào)用,盡量的減少內(nèi)存分配,也就是少new對象。
假設(shè)一條數(shù)據(jù)線上有非常多的點,對每個點都進(jìn)行映射到屏幕位置的計算,勢必要分配很多對象??紤]到是在單個線程:主線程繪制,我采用了單例來保留處理前后的結(jié)果。(MpAndroidChart采用對象池來處理內(nèi)存的分配問題)


2. 減少不必要的繪制
若你把圖譜放大:

上圖中:藍(lán)色區(qū)域為數(shù)據(jù)的范圍,黑色的區(qū)域為屏幕上圖譜的范圍。
很明顯,我們只能看到,手機(jī)屏幕中的圖譜區(qū)域顯示的部分?jǐn)?shù)據(jù)視圖。
所以在繪圖的時候,只選擇繪制可見的數(shù)據(jù)范圍是比較理智的。

3. 減少計算
計算是耗時的,當(dāng)你的計算非常耗時的時候,圖譜就顯的非常卡頓,所以減少計算是非常有必要的。
有這樣的一種情況:圖譜上有很多點,當(dāng)你點擊一個點的時候,要顯示這個點的信息。怎么確定是你點擊的那個點呢?一般來說是要遍歷你圖上所有的點,每個點距離你點擊的距離更近,那個點就是你想要的點了(HelloCharts是這么處理的),但經(jīng)驗證,這樣的計算是非常耗時的,點數(shù)稍微一多,譜圖就卡頓了。LChart采用二分查找法,快速的命中你想要的點,大大減少計算上的耗時,效果是很理想的。
代碼貼上來占據(jù)篇幅,地址在項目的data/line.java 這個類下,如有興趣,自行查看
最后但不是最后
關(guān)于LChart,關(guān)鍵的幾個地方我大致說了下,詳細(xì)的使用參見github上的demo。
也許你仍有很多疑惑,So,提出來,后續(xù)我也會逐漸的寫出來,完善它。
項目地址:https://github.com/linheimx/LChart,歡迎star,issue : )