作者:JessYan
連結:https://juejin.im/post/5ba197e46fb9a05d0b142c62
原文地址:https://www.jianshu.com/p/2aded8bb6ede
該系列的上一篇文章:
-
騷年你的螢幕適配方式該升級了!-今日頭條適配方案https://juejin.im/post/5b7a29736fb9a019d53e7ee2
1、前言
ok,根據上一篇文章 騷年你的螢幕適配方式該升級了!-今日頭條適配方案 的承諾,本文是這個系列的第二篇文章,這篇文章會詳細講解 smallestWidth 限定符螢幕適配方案
瞭解我的朋友一定知道,MVPArms 一直使用的是 鴻神 的 AndroidAutoLayout 螢幕適配方案,得益於 AndroidAutoLayout 的便捷,所以我對螢幕適配領域研究的不是很多,AndroidAutoLayout 停止維護後,我也一直在找尋著替代方案,直到 今日頭條螢幕適配方案 刷屏,後來又無意間看到了 smallestWidth 限定符螢幕適配方案,這才慢慢的將研究方向轉向了螢幕適配領域。
最近一個月才開始慢慢惡補 Android 螢幕適配的相關知識,對這兩個方案也進行了更深入的研究,可以說從一個小白慢慢成長而來,所以我明白小白的痛,因此在上一篇文章 騷年你的螢幕適配方式該升級了!-今日頭條適配方案 中,把 今日頭條螢幕適配方案 講得非常的細,儘量把每一個知識點都描述清晰,深怕小白漏掉每一個細節,這篇文章我也會延續上一篇文章的優良傳統,將 smallestWidth 限定符螢幕適配方案 的每一個知識點都描述清晰。
順便說一句,感謝大家對 AndroidAutoSize 的支援,我只是在上一篇文章中提了一嘴我剛釋出的螢幕適配框架 AndroidAutoSize,還沒給出詳細的介紹和原理剖析 (原計劃在本系列的第三篇文章中釋出),AndroidAutoSize 就被大家推上了 Github Trending,一個多星期就拿了 2k+ stars,隨著關註度的增加,我在這段時間裡也累壞了,issues 就沒斷過,不到半個月就提交了 200 多次 commit,但累並快樂著,在這裡要再次感謝大家對 AndroidAutoSize 的認可。
2、談談對百分比庫的看法
是這樣的,在上篇文章中有一些兄弟提了一些觀點,我很是認同,但是我站在執行者的角度來看待這個問題,也有一些不同的觀點,以下是我在上篇文章中的回覆
大家要註意了!這些觀點其實針對的是所有以百分比縮放佈局的庫,而不只是今日頭條螢幕適配方案,所以這些觀點也同樣適用於 smallestWidth 限定符螢幕適配方案,這點有很多人存在誤解,所以一定要註意!
上圖的每一個方框都代表一種 Android 裝置的螢幕,Android 的 系統碎片化、機型以及螢幕尺寸碎片化、螢幕解析度碎片化 有多嚴重大家可以透過 友盟指數 瞭解一下,有些時候在某些事情的決斷標準上,並不能按照事情的對錯來決斷,大多數情況還是要分析成本,收益等多種因素,透過利弊來決斷,每個人的利弊標準又都不一樣,所以每個人的觀點也都會有差別,但也都應該得到尊重,所以我只是說說自己的觀點,也不否認任何人的觀點。
方案是死的人是活的,在某些大屏手機或平板電腦上,您也可以採用其他適配方案和百分比庫結合使用,比如針對某個螢幕區間的裝置單獨出一套設計圖以顯示比小螢幕手機更多更精細的內容,來達到與百分比庫互補的效果,沒有一個方案可以說自己是完美的,但我們能清晰的認識到不同方案的優缺點,將它們的優點相結合,才能應付更複雜的開發需求,產出最好的產品。
友情提示: 下麵要介紹的 smallestWidth 限定符螢幕適配方案,原理也同樣是按照百分比縮放佈局,理論上也會存在上面所說的 大屏手機和小屏手機顯示的內容相同 的問題,選擇與否請仔細斟酌。
3、簡介 smallestWidth 限定符適配方案
這個方案的的使用方式和我們平時在佈局中取用 dimens 無異,核心點在於生成 dimens.xml 檔案,但是已經有大神幫我們做了這 一步
-
https://www.jianshu.com/p/1302ad5a4b04
├── src/main
│ ├── res
│ ├── ├──values
│ ├── ├──values-800x480
│ ├── ├──values-860x540
│ ├── ├──values-1024x600
│ ├── ├──values-1024x768
│ ├── ├──...
│ ├── ├──values-2560x1440
如果有人還記得上面這種 寬高限定符螢幕適配方案 的話,就可以把 smallestWidth 限定符螢幕適配方案 當成這種方案的升級版,smallestWidth 限定符螢幕適配方案 只是把 dimens.xml 檔案中的值從 px 換成了 dp,原理和使用方式都是沒變的,這些在上面的文章中都有介紹,下麵就直接開始剖析原理,smallestWidth 限定符螢幕適配方案 長這樣?
├── src/main
│ ├── res
│ ├── ├──values
│ ├── ├──values-sw320dp
│ ├── ├──values-sw360dp
│ ├── ├──values-sw400dp
│ ├── ├──values-sw411dp
│ ├── ├──values-sw480dp
│ ├── ├──...
│ ├── ├──values-sw600dp
│ ├── ├──values-sw640dp
4、原理
其實 smallestWidth 限定符螢幕適配方案 的原理也很簡單,開發者先在專案中根據主流螢幕的 最小寬度 (smallestWidth) 生成一系列 values-sw
如果系統根據當前裝置螢幕的 最小寬度 (smallestWidth) 沒找到對應的 values-sw
系統會根據當前裝置螢幕的 最小寬度 來匹配 values-sw
這就要說到,移動裝置都是允許螢幕可以旋轉的,當螢幕旋轉時,螢幕的高寬就會互換,加上 最小 這兩個字,是因為這個方案是不區分螢幕方向的,它只會把螢幕的高度和寬度中值最小的一方認為是 最小寬度,這個 最小寬度 是根據螢幕來定的,是固定不變的,意思是不管您怎麼旋轉螢幕,只要這個螢幕的高度大於寬度,那系統就只會認定寬度的值為 最小寬度,反之如果螢幕的寬度大於高度,那系統就會認定螢幕的高度的值為 最小寬度.
如果想讓螢幕寬度隨著螢幕的旋轉而做出改變該怎麼辦呢?可以再根據 values-w
如果想區分螢幕的方向來做適配該怎麼辦呢?那就只有再根據 螢幕方向限定符 生成一套資源檔案咯,字尾加上 -land 或 -port 即可,像這樣,values-sw400dp-land (最小寬度 400 dp 橫向),values-sw400dp-port (最小寬度 400 dp 縱向)。
4.2 smallestWidth 的值是怎麼算的
要先算出當前裝置的 smallestWidth 值我們才能知道當前裝置該匹配哪個 values-sw
ok,還是按照上一篇文章的敘述方式,現在來舉慄說明,幫助大家更好理解。
我們假設裝置的螢幕資訊是 1920 * 1080、480 dpi
根據上面的規則我們要在螢幕的高度和寬度中選擇值最小的一方作為最小寬度,1080 < 1920,明顯 1080 px 就是我們要找的 最小寬度 的值,但 最小寬度 的單位是 dp,所以我們要把 px 轉換為 dp
幫助大家再鞏固下基礎,下麵的公式一定不能再忘了!
px / density = dp,DPI / 160 = density,所以最終的公式是 px / (DPI / 160) = dp
所以我們得到的 最小寬度 的值是 360 dp (1080 / (480 / 160) = 360)。
現在我們已經算出了當前裝置的最小寬度是 360 dp,我們曉得系統會根據這個 最小寬度 幫助我們匹配到 values-sw360dp 檔案夾下的 dimens.xml 檔案,如果專案中沒有 values-sw360dp 這個檔案夾,系統才會去匹配相近的 values-sw
dimens.xml 檔案是整個方案的核心所在,所以接下來我們再來看看 values-sw360dp 檔案夾中的這個 dimens.xml 是根據什麼原理生成的。
4.3 dimens.xml 生成原理
因為我們在專案佈局中取用的 dimens 的實際值,來源於根據當前裝置螢幕的 最小寬度 所匹配的 values-sw
說到 dimens.xml 的生成,就要涉及到兩個因數,第一個因素是 最小寬度基準值,第二個因素就是您的專案需要適配哪些 最小寬度,通俗理解就是需要生成多少個 values-sw
4.3.1 第一個因素
最小寬度基準值 是什麼意思呢?簡單理解就是您需要把裝置的螢幕寬度分為多少份,假設我們現在把專案的 最小寬度基準值 定為 360,那這個方案就會理解為您想把所有裝置的螢幕寬度都分為 360 份,方案會幫您在 dimens.xml 檔案中生成 1 到 360 的 dimens 取用,比如 values-sw360dp 中的 dimens.xml 是長這樣的:
<resources>
<dimen name="dp_1">1dpdimen>
<dimen name=“dp_2”>2dpdimen>
<dimen name=“dp_3”>3dpdimen>
<dimen name=“dp_4”>4dpdimen>
<dimen name=“dp_5”>5dpdimen>
<dimen name=“dp_6”>6dpdimen>
<dimen name=“dp_7”>7dpdimen>
<dimen name=“dp_8”>8dpdimen>
<dimen name=“dp_9”>9dpdimen>
<dimen name=“dp_10”>10dpdimen>
…
<dimen name=“dp_356”>356dpdimen>
<dimen name=“dp_357”>357dpdimen>
<dimen name=“dp_358”>358dpdimen>
<dimen name=“dp_359”>359dpdimen>
<dimen name=“dp_360”>360dpdimen>
resources>
values-sw360dp 指的是當前裝置螢幕的 最小寬度 為 360dp (該裝置高度大於寬度,則最小寬度就是寬度,所以該裝置寬度為 360dp),把螢幕寬度分為 360 份,剛好每份等於 1dp,所以每個取用都遞增 1dp,值最大的 dimens 取用 dp_360 值也是 360dp,剛好改寫螢幕寬度.
下麵再來看看將 最小寬度基準值 定為 360 時,values-sw400dp 中的 dimens.xml 長什麼樣:
<resources>
<dimen name="dp_1">1.1111dpdimen>
<dimen name=“dp_2”>2.2222dpdimen>
<dimen name=“dp_3”>3.3333dpdimen>
<dimen name=“dp_4”>4.4444dpdimen>
<dimen name=“dp_5”>5.5556dpdimen>
<dimen name=“dp_6”>6.6667dpdimen>
<dimen name=“dp_7”>7.7778dpdimen>
<dimen name=“dp_8”>8.8889dpdimen>
<dimen name=“dp_9”>10.0000dpdimen>
<dimen name=“dp_10”>11.1111dpdimen>
…
<dimen name=“dp_355”>394.4444dpdimen>
<dimen name=“dp_356”>395.5556dpdimen>
<dimen name=“dp_357”>396.6667dpdimen>
<dimen name=“dp_358”>397.7778dpdimen>
<dimen name=“dp_359”>398.8889dpdimen>
<dimen name=“dp_360”>400.0000dpdimen>
resources>
values-sw400dp 指的是當前裝置螢幕的 最小寬度 為 400dp (該裝置高度大於寬度,則最小寬度就是寬度,所以該裝置寬度為 400dp),把螢幕寬度同樣分為 360份,這時每份就等於 1.1111dp 了,每個取用都遞增 1.1111dp,值最大的 dimens 取用 dp_360 同樣剛好改寫螢幕寬度,為 400dp.
透過兩個 dimens.xml 檔案的比較,dimens.xml 的生成原理一目瞭然,方案會先確定 最小寬度基準值,然後將每個 values-sw
這樣就能保證不管將專案執行到哪個裝置上,只要當前裝置能匹配到對應的 values-sw
說到這裡,那大家就應該就會明白我為什麼會說 smallestWidth 限定符螢幕適配方案 的原理也同樣是按百分比進行佈局,如果在佈局中,一個 View 的寬度取用 dp_100,那不管執行到哪個裝置上,這個 View 的寬度都是當前裝置螢幕總寬度的 360分之100,前提是專案提供有當前裝置螢幕對應的 values-sw
其實 smallestWidth 限定符螢幕適配方案 的原理和 今日頭條螢幕適配方案 挺像的,今日頭條螢幕適配方案 是根據螢幕的寬度或高度動態調整每個裝置的 density (每 dp 佔當前裝置螢幕多少畫素),而 smallestWidth 限定符螢幕適配方案 同樣是根據螢幕的寬度動態調整每個裝置 每份佔的 dp 值。
4.3.2 第二個因素
第二個因數是需要適配哪些 最小寬度?
比如您想適配的 最小寬度 有 320dp、360dp、400dp、411dp、480dp,那方案就會為您的專案生成 values-sw320dp、values-sw360dp、values-sw400dp、values-sw411dp、values-sw480dp 這幾個資源檔案夾,像這樣?
├── src/main
│ ├── res
│ ├── ├──values
│ ├── ├──values-sw320dp
│ ├── ├──values-sw360dp
│ ├── ├──values-sw400dp
│ ├── ├──values-sw411dp
│ ├── ├──values-sw480dp
方案會為您需要適配的 最小寬度,在專案中生成一系列對應的 values-sw
那是不是 values-sw
也不是,因為每個 values-sw
所以一定要合理分配 values-sw
5、驗證方案可行性
原理講完了,我們還是按照老規矩,來驗證一下這個方案是否可行?
假設設計圖總寬度為 375 dp,一個 View 在這個設計圖上的尺寸是 50dp * 50dp,這個 View 的寬度佔整個設計圖寬度的 13.3% (50 / 375 = 0.133)
在使用 smallestWidth 限定符螢幕適配方案 時,需要提供 最小寬度基準值 和需要適配哪些 最小寬度,我們就把 最小寬度基準值 設定為 375 (和 設計圖 一致),這時方案就會為我們需要適配的 最小寬度 生成對應的 values-sw
下麵就來驗證下在使用 smallestWidth 限定符螢幕適配方案 的情況下,這個 View 與螢幕寬度的比例在解析度不同的裝置上是否還能保持和設計圖中的比例一致
5.1 驗證裝置 1
裝置 1 的螢幕總寬度為 1080 px,螢幕總高度為 1920 px,DPI 為 480。
裝置 1 的螢幕高度大於螢幕寬度,所以 裝置 1 的 最小寬度 為螢幕寬度,再根據公式 px / (DPI / 160) = dp,求出 裝置 1 的 最小寬度 的值為 360 dp (1080 / (480 / 160) = 360)。
根據 裝置 1 的 最小寬度 應該匹配的是 values-sw360dp 這個檔案夾,假設 values-sw360dp 檔案夾及裡面的 dimens.xml 已經生成,且是按 最小寬度基準值 為 375 生成的,360 / 375 = 0.96,所以每份佔的 dp 值為 0.96,dimens.xml 裡面的內容是長下麵這樣的
<resources>
<dimen name="dp_1">0.96dpdimen>
<dimen name=“dp_2”>1.92dpdimen>
<dimen name=“dp_3”>2.88dpdimen>
<dimen name=“dp_4”>3.84dpdimen>
<dimen name=“dp_5”>4.8dpdimen>
…
<dimen name=“dp_50”>48dpdimen>
…
<dimen name=“dp_371”>356.16dpdimen>
<dimen name=“dp_372”>357.12dpdimen>
<dimen name=“dp_373”>358.08dpdimen>
<dimen name=“dp_374”>359.04dpdimen>
<dimen name=“dp_375”>360dpdimen>
resources>
可以看到這個 View 在佈局中取用的 dp_50,最終在 values-sw360dp 中定格在了 48 dp,所以這個 View 在 裝置 1 上的高寬都為 48 dp,系統最後會將高寬都換算成 px,根據公式 dp * (DPI / 160) = px,所以這個 View 的高寬換算為 px 後等於 144 px (48 * (480 / 160) = 144)。
144 / 1080 = 0.133,View 的實際寬度與 螢幕總寬度 的比例和 View 在設計圖中的比例一致 (50 / 375 = 0.133),所以完成了等比例縮放。
某些裝置的高寬是和 裝置 1 相同的,但是 DPI 可能不同,而由於 smallestWidth 限定符螢幕適配方案 並沒有像 今日頭條螢幕適配方案 一樣去自行修改 density,所以系統就會使用預設的公式 DPI / 160 求出 density,density 又會影響到 dp 和 px 的換算,因此 DPI 的變化,是有可能會影響到 smallestWidth 限定符螢幕適配方案 的。
所以我們再來試試在這種特殊情況下 smallestWidth 限定符螢幕適配方案 是否也能完成適配。
5.2 驗證裝置 2
裝置 2 的螢幕總寬度為 1080 px,螢幕總高度為 1920 px,DPI 為 420。
裝置 2 的螢幕高度大於螢幕寬度,所以 裝置 2 的 最小寬度 為螢幕寬度,再根據公式 px / (DPI / 160) = dp,求出 裝置 2 的 最小寬度 的值為 411.429 dp (1080 / (420 / 160) = 411.429)
根據 裝置 2 的 最小寬度 應該匹配的是 values-sw411dp 這個檔案夾,假設 values-sw411dp 檔案夾及裡面的 dimens.xml 已經生成,且是按 最小寬度基準值 為 375 生成的,411 / 375 = 1.096,所以每份佔的 dp 值為 1.096,dimens.xml 裡面的內容是長下麵這樣的
<resources>
<dimen name="dp_1">1.096dpdimen>
<dimen name=“dp_2”>2.192dpdimen>
<dimen name=“dp_3”>3.288dpdimen>
<dimen name=“dp_4”>4.384dpdimen>
<dimen name=“dp_5”>5.48dpdimen>
…
<dimen name=“dp_50”>54.8dpdimen>
…
<dimen name=“dp_371”>406.616dpdimen>
<dimen name=“dp_372”>407.712dpdimen>
<dimen name=“dp_373”>408.808dpdimen>
<dimen name=“dp_374”>409.904dpdimen>
<dimen name=“dp_375”>411dpdimen>
resources>
可以看到這個 View 在佈局中取用的 dp_50,最終在 values-sw411dp 中定格在了 54.8dp,所以這個 View 在 裝置 2 上的高寬都為 54.8 dp,系統最後會將高寬都換算成 px,根據公式 dp * (DPI / 160) = px,所以這個 View 的高寬換算為 px 後等於 143.85 px (54.8 * (420 / 160) = 143.85)。
143.85 / 1080 = 0.133,View 的實際寬度與 螢幕總寬度 的比例和 View 在設計圖中的比例一致 (50 / 375 = 0.133),所以完成了等比例縮放。
雖然 View 在 裝置 2 上的高寬是 143.85 px,比 裝置 1 的 144 px 少了 0.15 px,但是誤差非常小,整體的比例並沒有發生太大的變化,是完全可以接受的。
這個誤差是怎麼引起的呢,因為 裝置 2 的 最小寬度 的實際值是 411.429 dp,但是匹配的 values-sw411dp 捨去了小數點後面的位數 (切記!系統會去尋找小於或等於 411.429 dp 的 values-sw
可以看到即使在高寬一樣但 DPI 不一樣的裝置上,smallestWidth 限定符螢幕適配方案 也能完成等比例適配,證明這個方案是可行的,如果大家還心存疑慮,也可以再試試其他解析度的裝置,其實到最後得出的比例都是在 0.133 左右,唯一的變數就是第二個因數,如果您生成的 values-sw
優點
1、非常穩定,極低機率出現意外
2、不會有任何效能的損耗
3、適配範圍可自由控制,不會影響其他三方庫
4、在外掛的配合下,學習成本低
缺點
1、在佈局中取用 dimens 的方式,雖然學習成本低,但是在日常維護修改時較麻煩
2、侵入性高,如果專案想切換為其他螢幕適配方案,因為每個 Layout 檔案中都存在有大量 dimens 的取用,這時修改起來工作量非常巨大,切換成本非常高昂
3、無法改寫全部機型,想改寫更多機型的做法就是生成更多的資源檔案,但這樣會增加 App 體積,在沒有改寫的機型上還會出現一定的誤差,所以有時需要在適配效果和佔用空間上做一些抉擇
4、如果想使用 sp,也需要生成一系列的 dimens,導致再次增加 App 的體積
、5不能自動支援橫豎屏切換時的適配,如上文所說,如果想自動支援橫豎屏切換時的適配,需要使用 values-w
6、不能以高度為基準進行適配,考慮到這個方案的名字本身就叫 最小寬度限定符適配方案,所以在使用這個方案之前就應該要知道這個方案只能以寬度為基準進行適配,為什麼現在的螢幕適配方案只能以高度或寬度其中的一個作為基準進行適配,請看 這裡 https://github.com/JessYanCoding/AndroidAutoSize/issues/8
使用中的問題
這時有人就會問了,設計師給的設計圖只標註了 px,使用這個方案時,那不是還要先將 px 換算成 dp?
其實也可以不用換算的,那這是什麼騷操作呢?
很簡單,你把設計圖的 px 總寬度設定成 最小寬度基準值 就可以了,還是以前面驗證可行性的例子
我們在前面驗證可行性時把 最小寬度基準值 設定成了 375,為什麼是 375 呢?因為設計圖的總寬度為 375 dp,如果換算成 px,總寬度就是 750 px,我們這時把 最小寬度基準值 設定成 750,然後看看 values-sw360dp 中的 dimens.xml 長什麼樣
<resources>
<dimen name="px_1">0.48dpdimen>
<dimen name=“px_2”>0.96dpdimen>
<dimen name=“px_3”>1.44dpdimen>
<dimen name=“px_4”>1.92dpdimen>
<dimen name=“px_5”>2.4dpdimen>
…
<dimen name=“px_50”>24dpdimen>
…
<dimen name=“px_100”>48dpdimen>
…
<dimen name=“px_746”>358.08dpdimen>
<dimen name=“px_747”>358.56dpdimen>
<dimen name=“px_748”>359.04dpdimen>
<dimen name=“px_749”>359.52dpdimen>
<dimen name=“px_750”>360dpdimen>
resources>
360 dp 被分成了 750 份,相比之前的 375 份,現在 每份佔的 dp 值 正好減少了一半,還記得在驗證可行性的例子中那個 View 的尺寸是多少嗎?50dp * 50dp,如果設計圖只標註 px,那這個 View 在設計圖上的的尺寸應該是 100px * 100px,那我們直接根據設計圖上標註的 px,想都不用想直接在佈局中取用 px_100 就可以了,因為在 375 份時的 dp_50 剛好等於 750 份時的 px_100 (值都是 48 dp),所以這時的適配效果和之前驗證可行性時的適配效果沒有任何區別
看懂了嗎?直接將 最小寬度基準值 和佈局中的取用都以 px 作為單位就可以直接填寫設計圖上標註的 px!
6、總結
關於文中所列出的優缺點,列出的缺點數量確實比列出的優點數量多,但 缺點 3,缺點 4,缺點 5 其實都可以歸納於 佔用 App 體積 這一個缺點,因為他們都可以透過增加資源檔案來解決問題,而 缺點 6 則是這個方案的特色,只能以寬度為基準進行適配,這個從這個方案的名字就能看出。
請大家千萬不要曲解文章的意思,不要只是單純的對比優缺點的數量,缺點的數量大於優點的數量就一定是這個方案不行?沒有一個方案是完美的,每個人的需求也都不一樣,作為一篇科普類文章我只可能把這個方案描述得盡可能的全面。
這個方案能給你帶來什麼,不能給你帶來什麼,我必須客觀的描述清楚,這樣才有助你做出決定,你應該註重的是在這些優缺點裡什麼是我能接受的,什麼是我不能接受的,是否能為了某些優點做出某些妥協,而不只是單純的去看數量,這樣毫無意義,有些人就是覺得穩定性最重要,其他的都可以做出妥協,那其他缺點對於他來說都是無所謂的。
好了,這個系列的第二篇文章講完了,這篇文章也是按照上篇文章的優良傳統,寫的非常詳細,哪怕是新手我相信也應該能看懂,為什麼這麼多人都不知道自己該選擇什麼樣的方案,就是因為自己都沒搞懂這些方案的原理,懂了原理過後才知道這些方案是否是自己想要的。
接下來的第三篇文章會詳細講解兩個方案的深入對比以及該如何選擇,並剖析我根據 今日頭條螢幕適配方案 最佳化的螢幕適配框架 AndroidAutoSize 的原理,敬請期待
-
https://github.com/JessYanCoding/AndroidAutoSize
如果大家想使用 smallestWidth 限定符螢幕適配方案,可以參考 這篇文章 https://www.jianshu.com/p/1302ad5a4b04,裡面提供有自動生成資源檔案的外掛和 Demo,由於我並沒有在專案中使用 smallestWidth 限定符螢幕適配方案,所以如果在文章中有遺漏的知識點請諒解以及補充,感謝!
●編號372,輸入編號直達本文
●輸入m獲取到文章目錄
Java程式設計
更多推薦《18個技術類公眾微信》
涵蓋:程式人生、演演算法與資料結構、駭客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。