中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

安卓開發(fā)常用工具和第三方庫匯總

2018-07-20    來源:編程學習網(wǎng)

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

我的名字叫 Ryan Cooke 我在 Pinterest 的核心體驗團隊工作。今天在這里我會談?wù)摳鞣N Android 庫:它們各自的優(yōu)點,缺點和其他相關(guān)知識。目的是高效地概述盡可能多的庫,這樣,當你遇到一個問題的時候,你知道這是不是個已經(jīng)解決的問題?什么樣的方案更好?同時也能幫助你避免那些陷阱。

選擇正確的庫意味著你可以擁有一個已經(jīng)成熟的更好的解決方案,而不是花費三個月來重新構(gòu)建它。了解這些庫是第一步。

我聽到很多人想要實現(xiàn)第一個庫, 我們難道不能用 Async 任務(wù)或原生的東西來做嗎? Google 覺得,如果市面上已經(jīng)有一個解決方案了,他們就不想建立一個一模一樣的競品。他們在多個地方多次表達過這個想法。但是你應(yīng)該知道,你還有一些別的選擇。

一般提示

庫最有價值的地方在于 可逆 :你將庫添加到你的應(yīng)用程序中,之后也可以將其刪除(沒有任何開銷)。隨時都能拿出來。不是所有的東西都可以這樣,但如果它可以的話,請把它做成一個庫,而不是和你的應(yīng)用終生綁在一起。

一個更好的方法是在把你的庫封裝起來。如果你自己的類調(diào)用了庫的方法,那么這樣做就有著許多的好處,可以讓使用者調(diào)用你自己的 API。例如,在某些情況下如果庫返回異常,你想在 API 里截獲它。你只用修改一個文件。有一個封裝器讓你的庫更易用些。

如果你正在做一個庫,你的團隊里面的某些人可能已經(jīng)開始使用它了,他們知道該如何調(diào)用你的庫,而不用你的封裝。這個檢查樣式會在編譯的時候拋出異常,或者在應(yīng)用中當他們?yōu)檫B接類使用 import 語句時,提示他們“不要使用連接類,使用封裝的 API”。你還會指出不要在這個特定文件上這樣做。如果你不這樣做,封裝器用處就不大,因為人們最終會繞過它。

另外, 對第三方庫做單元測試 也是一個好主意。你需要這些測試,如果你正在使用 Joda-Time 這樣的庫,你可以使用單元測試來了解它奇怪的邊界情況。你甚至可以通過單元測試來了解它的工作原理。你可能會發(fā)現(xiàn),如果你不用 add day 方法而是給今天加一的話,你可能會出現(xiàn)二月三十日的情況。

在 Android 的世界中,我們必須考慮 函數(shù)數(shù)量限制(64,000) 。( 我在說第三方函數(shù)庫的函數(shù)數(shù)量,它們會被精簡掉 )。有一個網(wǎng)站[函數(shù)數(shù)量](http://methodscount.com),你可以上傳你的庫,Gradle 導入語句,然后它會告訴你這個庫有多少個方法(這是件很棒的事情,特別是當你想使用該庫的時候)。使用 ProGuard,許多庫將會變得很小。這個方法使你只會包含庫中被引用的部分,但是在使用庫之前是很難預(yù)測你將要使用的內(nèi)容的。有些時候你可以這樣做,“我知道我只使用庫的這個方法”,看看它有多小。

Dex函數(shù)計數(shù) 會在你的 gradle 里,你也可以在你自己的編譯系統(tǒng)上這么做,跟蹤你應(yīng)用程序中函數(shù)的總個數(shù)。 Apk-method-count 是一個很棒的工具。你可以拖動你的 APK,看看它有多少個方法(63,905 個方法,我喜歡生活在 64,000 的邊緣)。在 MultiDex 限制出現(xiàn)之前,你添加的每個方法仍將減慢那些舊設(shè)備的啟動時間。雖然你的船已經(jīng)航行,不受 MultiDexing 的限制,十萬種方法和十二萬種方法之間還是有差別的。更少的方法總是有好處的。 Instagram 就是以 從庫 中提取所需的東西而不是使用完整的庫而聞名的。這是一個很好的實踐,如果你有精力這樣做的話。

除此之外,我還建議關(guān)注 流行的成熟庫 。每個月(特別是如果你訂閱了 Reddit Android 開發(fā)者),你將會聽到最新,最酷的庫。庫越成熟,就會越受歡迎。與現(xiàn)有的項目一起工作,兼容性問題就越少。無論何時遇到問題,stackoverflow 那里都會有答案。

另外,請注意特殊的方法。這是不符合 Java 標準的東西。如果你正在構(gòu)建完全不同的布局,那么很可能會有兼容性問題。這時采用庫就會變得更加猶豫。

社交登錄

Facebook 是社交登錄的黃金標準( 如果你不喜歡 Facebook 的實現(xiàn),情況只會變得更糟 )。他們提供測試用戶,你可以使用這些測試賬戶來測試。不再需要假帳戶了,你應(yīng)該使用他們的測試帳戶 - 它們工作的更好。我看過有人犯過這樣的錯誤,你不能假設(shè)每個 Facebook 用戶都有電子郵件。大約 10 到 15% 的 Facebook 用戶沒有電子郵件。如果你期待電子郵件,這可能是 10 到 15% 的注冊失敗的神秘原因。他們需要密鑰散列( 這是一個隨機序列,某段代碼打印出的鍵值哈希 ),所以你不必處理它,不用理會它。如果你想申請些其他的瘋狂權(quán)限,他們現(xiàn)在已經(jīng)鎖定了這些權(quán)限。他們需要先看看你打算如何使用這些權(quán)限,如果你有這個瘋狂的想法而且應(yīng)用還沒有開發(fā)好,請?zhí)崆案嬷麄儭?/p>

登錄和注冊時,請記錄你所得到的錯誤。這是我們?nèi)绾伟l(fā)現(xiàn)由于沒有電子郵件,10 到 15% 的注冊失敗的方法。有時候記錄錯誤可能是找到你不了解的東西的最有效的方法。

還有很多其他登錄選項:Twitter,LinkedIn,Google。我的心態(tài)是(特別是 Twitter,LinkedIn),雖然他們很受歡迎,但往往不值得的嘗試。你會看到不到 2% 的注冊率,除非是一個非常好的場景。 LinkedIn 提供了非常具有挑戰(zhàn)性的 API( 這不是我原來的單詞,但是 PR 告訴我,我應(yīng)該改變它 )。 Twitter,他們不提供很多信息,但你可以 轉(zhuǎn)到此鏈接 , 并且說我需要電子郵件和基本信息,他們會給大家授予權(quán)限。但總體來說,除非你的架構(gòu)非常好,這些都會增加你應(yīng)用的復(fù)雜性,。

Google 情況比較復(fù)雜。在 Android 上,很多人都會擁有 Google 帳戶。如果他們沒有 Google 帳戶,是非常奇怪的。但是你可以從 Google 登錄中獲得很多功能 - 你可以獲取電子郵件提示和其他東西。此外,登錄 UI 是十分丑陋的。還有點慢,所以你必須考慮加載模式的對話框。

聯(lián)網(wǎng)

如果你使用本地庫,那么有兩個大名鼎鼎的庫:Retrofit,Volley。還有 native HTML URL Connect(通常不推薦)。對于 Retrofit 和 Volley 來說,你經(jīng)常會看到些比較,你會看到 Volley 比 Retrofit 做的更多(例如圖像下載和 neat )。這具有欺騙性。

Retrofit 是由 Square 建造的,他們有一個哲學,他們的庫會盡可能少做事情。他們試圖讓庫嚴格地解決具體的問題,解決這個問題時,強制執(zhí)行良好的實踐。Retrofit 可能是他們最好的例子。這段代碼( 見幻燈片 )是我在一個應(yīng)用程序中使用 Retrofit 的示例,我必須為我的 API 調(diào)用創(chuàng)建一個非常干凈的接口。

Get more development news like this

Volley 給你足夠的繩子吊死自己。你可以使用 Volley,很容易用錯。Retrofit 更好地強化了最佳實踐,我喜歡這樣的做法。

很多時候你會聽到 OkHttp:這是真正的幕后大舉提升網(wǎng)絡(luò)性能的功臣。它已經(jīng)在 Android 4.4 的 native 里面了。

網(wǎng)絡(luò)調(diào)試

考慮到網(wǎng)絡(luò)調(diào)試,你有網(wǎng)絡(luò)調(diào)用正在進行,你想了解發(fā)生了些什么。

Stetho

Stetho 是一個很好的選擇。它是 Facebook 開發(fā)的。它為你的網(wǎng)絡(luò)調(diào)用提供了 Chrome 開發(fā)者工具視圖。它還提供了許多其他的好東西:可以查看你的數(shù)據(jù)庫,看看那里發(fā)生了什么;可以看到你的布局,如果你不知道屏幕上發(fā)生了什么。其中需要注意的是,你必須在每次運行時啟動它,否則它會自動關(guān)閉。雖然時間是準確的,但它會使你網(wǎng)絡(luò)調(diào)用的時間更長。

HttpLoggingInterceptor

我個人傾向于另一個簡單的 HttpLoggingInterceptor。你將攔截器添加到你的網(wǎng)絡(luò)請求中,并將其打印在日志文件上。你也可以看到一些 JSON 文件。有一堆類似的東西都命名為 logging 攔截器。使用 Square 的標準 HTTP 日志記錄可以讓你更輕松地瀏覽,非常方便。

圖片

作為在 Pinterest 工作的人,圖片很重要。如果你正在做圖片相關(guān)的應(yīng)用,你可能希望使用第三方庫來處理圖片緩存,圖片下載和圖片大小調(diào)整。

Picasso,Glide

圖片處理庫里最有名的兩個庫是 Picasso 和 Glide。他們有著非常相似的接口;對于大多數(shù)標準用戶來說接口基本相同。

Picasso 較小。最新版本從 2,879 行縮小到 849 行。但是,Glide 傾向于提供你想要的每個功能:它可以加載 GIF,也可以顯示視頻預(yù)覽圖像。

如果你正在加載圖片,Picasso 比較合適。它更受歡迎:它有更多的文檔,更多的支持。兩個庫都很好。如果你一直都有些奇怪的場景,你可以冒險使用 Glide。如果你的使用場景很標準,Picasso 是一個不錯的選擇。

提示

我已經(jīng)提到我在 Pinterest 工作,而且圖像對我的工作很重要。我必須扔出一堆關(guān)于圖像的提示。

人們都沒有做最簡單的事情,因為這些庫沒有這樣做,這件簡單的事情就是在列表中預(yù)取。每當你滾動列表時,你都會看到圖像在加載。如果你預(yù)取了下一個或兩個圖像,那么當你滾動時,將會減少幀丟失。這會給你帶來更好的體驗,不需要等待加載了。如果你預(yù)取的圖像太多,資源就會競爭,也不好,但預(yù)取下一個或兩個圖像一定會帶來更好的體驗。

除此之外,這些庫都不能解決你圖像的內(nèi)存問題。最簡單的做法是禁用圖像,然后計算出應(yīng)用程序中的圖像消耗了多少內(nèi)存。不使用圖像,計算出省下的內(nèi)存消耗。另外,釋放沒有顯示圖像的圖像,并將圖像的大小調(diào)整為你顯示的尺寸也可以幫助節(jié)省內(nèi)存。 Cloudinary 是一個很酷的托管服務(wù),你可以以特定的分辨率請求圖像。他們努力做到這點。但是,當你調(diào)整請求的圖像大小時,你必須確保你沒有通過請求類似的圖像來破壞緩存(所以這里有個平衡)。

我是 bigHeap 的粉絲。我們的一個的應(yīng)用程序,使用了 bigHeap 后,內(nèi)存崩潰降到原來的 1/4。 Google 不鼓勵使用它,因為它關(guān)閉了在后臺的其他應(yīng)用程序,因此應(yīng)用程序之間的切換并不是那么好。但在某些時候,這不是你的問題。垃圾回收也需要更長時間,你可以使用它來屏蔽內(nèi)存問題(你不應(yīng)該這么做)。一般來說,bigHeap 是好的。如果你去 Play Store,并且搜索 largeHeap,你可以下載一個很酷的應(yīng)用程序,它會顯示你手機上啟用了 bigHeap 的應(yīng)用程序。你會注意到現(xiàn)在幾乎每個人都陷入了困境,并且正在使用 bigHeap。

當你想到內(nèi)存和圖像時,這里有一個簡單的公式。有些人會問,“這是個兩千字節(jié)的 JPEG,為什么我的實際使用的內(nèi)存會這么大呢?” 使用的內(nèi)存是像素寬度乘以像素高度的四倍。這就是你期望的大小。它們的標準格式是 ARGB_8888 - 它用四個字節(jié)存儲顏色空間。如果你使用 RGB_565,你可以將其減少到兩倍。但是顏色彼此會非常相似,你會看到更少的色彩空間,它也不能做 alpha,但它會減少一半的內(nèi)存使用量。你可以考慮在低端設(shè)備或低版本 API 上進行此操作。這是節(jié)省內(nèi)存不足問題的好方法。

Fresco

Facebook 發(fā)布了一個神奇的庫,解決了 API 21 之前的所有版本的內(nèi)存不足問題。在 API 21 之前,Android 系統(tǒng)中出現(xiàn)了一個錯誤,你可以在應(yīng)用程序內(nèi)存之外使用其他的內(nèi)存。但是會帶來些奇怪的情況:你的程序在舊設(shè)備上沒有問題,但在新設(shè)備上會表現(xiàn)更糟。因為它加載的方式與其他庫非常不同,所以它可以實現(xiàn)漸進式 JPEG 這樣的圖像,圖像在圖層中逐漸加載。但是,它們會更深入地耦合在你的應(yīng)用程序中。借助 Glide 和 Picasso,你可以將其與你的應(yīng)用隔離的很好。而不使用 imageViews,你必須使用它們的類型 Drawees,并且還會產(chǎn)生更多的孤島代碼。

如果你定位較低端的設(shè)備,你在舊設(shè)備上有更多的內(nèi)存需求,我建議你使用 Fresco。除此之外,我會堅持 Picasso 和 Glide。

內(nèi)存 - 泄漏

LeakCanary

LeakCanary 是當今內(nèi)存泄露的神器,它可以幫助你找到內(nèi)存泄露的地方。泄漏不是所有的內(nèi)存問題,但是值得留意。當你將 LeakCanary 添加到應(yīng)用程序中時,它會自動開始觀察你的 activity 的內(nèi)存泄漏。有一個我親眼所見的誤用是,他們將 LeakCanary 添加到應(yīng)用程序中。修復(fù)一個或兩個泄漏,然后就認為再沒有更多的內(nèi)存泄漏了。它只監(jiān)視了 activity。如果你在這里使用這個代碼( 看幻燈片 ),你可以讓它監(jiān)視 fragment。這并不意味著你不會在別處泄漏內(nèi)存。activity 和 fragment 是監(jiān)測的好地方,但如果你沒有將觀察者設(shè)置為對象,你是不知道所有的泄露的。

簡單來說,它的工作原理很酷。作為你引用的任何對象的弱引用:將其附加到你不再被引用的內(nèi)容中。你把它放在 destroy 代碼段。然后它做垃圾回收。如果對象仍然存在,這就是內(nèi)存泄漏,所以它知道什么對象依舊存在。它給你那個 home fragment 現(xiàn)場的相關(guān)引用。我覺得這很難理解(*有些人認為這很簡單,有人認為這很難。)

這里有個 view 的例子來做點簡單說明( 見幻燈片 )。你從底部開始(這就是泄露的東西)。我有 home fragment。 它被 pin grid fragment 引用 - pin grid fragment 是這個對象的父親。然后我們有這個奇怪的$ 0 - 它解釋說,這是一個可運行的對象。對象內(nèi)有一個處理程序包含一個 runnable。這段代碼(這不是我的),它是 Android 操作系統(tǒng)的,是處理程序的代碼。處理程序有個 runnalbe 正在運行。我需要確保處理程序不再保留 runnable。在這種情況下,我可以在視圖的 destroy 中清除所有的 runnable 和處理程序,這將修復(fù)這個內(nèi)存泄漏。

WeakHandler

你還可以使用這個隨機工具 WeakHandler,這使得處理程序引用都是弱引用。如果你觸發(fā)一個垃圾回收,就可以回收它們。它的缺點是可以被垃圾回收 - 如果你不希望它們被垃圾回收,那可能會出現(xiàn)意想不到的事情。值得注意的是,我遇到的大多數(shù)內(nèi)存泄漏都是無效的,它通常是一個正在運行的 non-missed 的類持有外部類 (這是最常見的地方) 。對于你的內(nèi)存泄漏,還需要一個 bug 分類的方法。沒有什么比你手機上有 70 個內(nèi)存泄漏, 而你不知道下一步該做什么更糟糕了。作為一個團隊,弄清楚當我們發(fā)現(xiàn)內(nèi)存泄漏時要做什么,總是一個好主意。

UI

我們都知道我們一直深陷泥潭。Activity 是舊標準。因為你想重用,所以有了 fragment。但是最后我們用 fragment 把 UI 顯示做的異常復(fù)雜。試試另一種方法,基于視圖的架構(gòu),它更流行。在基于視圖的架構(gòu)里,你有一個框架布局,而不用處理任何原生的 Android navigation 的東西,你可以用你想要的視圖替換內(nèi)部的框架布局里的任何東西。希望這能夠解決 fragment 的復(fù)雜性。

fragment 已經(jīng)被簡化了,而且更新了版本,它們現(xiàn)在更加穩(wěn)定,但是人們依舊爭論著需要有基于視圖的架構(gòu)。如果我們遵循這個論點,我們應(yīng)該看看一些庫(圖形的底部, 看幻燈片 )。

基于視圖的架構(gòu)

這個架構(gòu)是由 Mortar 和 Flow 引入的。我相信他們是第一批普及基于視圖的架構(gòu)的庫。 Flow 真正地遵循了基于視圖的架構(gòu),但是它們往往是一起的,而 Mortar 主要是 MVP 模式。當你開始實現(xiàn)基于視圖的架構(gòu)時,請注意這個奇怪的地方。

你還可以找到些更奇怪的地方,那就是如果你的應(yīng)用是基于 View 的話,你會遇到些隨機的問題,因為這個庫不是基于 View 的。它是基于 activity 的, 如果你的應(yīng)用是基于 view 的話,你得自己去解決那些問題。比如基于 View 的標準問題,例如 on-activity 的行為,許可等等。即使是后退按鈕和導航,你都不得不自己去解決,只要你是基于 View 的。

Mortar 和 Flow完成基本的導航功能,但它們并不解決所有常見問題(例如屏幕上保存的狀態(tài))。

Conductor正是為這些基于 View 的視圖而生的,它創(chuàng)建了一個解決方案:比如保存狀態(tài),轉(zhuǎn)換等等。但是你仍然會遇到兼容性問題。總的來說,他們是非常好的,他們是架構(gòu)不可知的,所以你可以采用你自己的 MV。

Scoop 來自 Lyft。他們在產(chǎn)品中使用它。它是經(jīng)過產(chǎn)品測試的基于視圖架構(gòu)的解決方案。它們不保存狀態(tài),所以 Lyft 無法保存狀態(tài)。在你將要使用基于視圖的架構(gòu)的主要常見問題中,這是最大的問題。切換很容易使用,但也很有限,這對于基于視圖的體系結(jié)構(gòu)來說有點令人失望,因為在這種架構(gòu)下,你往往可以實現(xiàn)很好的切換。

總的來說,如果你不需要保存狀態(tài),Scoop 是可用的,最安全的產(chǎn)品。Conductor 也很好。我會推薦這兩個庫。

模型 視圖 表示(MVP)

有幾個很好的 MVP 的庫。MVP 的基本思想是把邏輯代碼分離出來,這樣視圖部分,Core Android 的東西,會放在一起,然后 presenter 也是分開的,我們可以單元測試這個 presenter。理論上,我們可以改變視圖,而不必完全重寫業(yè)務(wù)邏輯。

有很多方法來做 MVP。我推薦的第一個庫是 Mosby 。即使你不使用 Mosby,他們也有很棒的教程和 Android 相關(guān)的文章( 比如 MVP 應(yīng)該是什么樣的,它如何工作 )。它主要能提供的功能是給你的 presenter 提供視圖狀態(tài)。

Nucleus也很類似。 Mortar ,作為 Mortar 和 Flow 的一部分,是它們早期的版本,它們越升級問題越多。我看到公司常常自己 構(gòu)建 MVP :在創(chuàng)建時,你將啟動你的 presenter; 銷毀時,你會停止你的 presenter 。每個 activity 或任何你的視圖持有的任何東西都會有一個 presenter。

所有的這些權(quán)衡,雖然聽起來很簡單,當你實際操作一個用例時,有很多邊緣案例要考慮。你有你的適配器,你的視圖項目。確保每個人理解的都一樣,并且找到能夠運用 MVP 的地方是最難的部分。但是這樣做的最終結(jié)果是你可以獲得更多的可單元測試代碼。你可以獲得更穩(wěn)定的代碼。

測試 - 性能

NimbleDroid

我有一堆關(guān)于測試的內(nèi)容,但我不想讓你們聽三個小時測試的東西,所以我們跳過使用 JUnit 4 進行單元測試。你有一個 Gradle 構(gòu)建系統(tǒng),有 Espresso。這些都是標配。性能測試是個非標的工具。

執(zhí)行性能測試有兩種主要的方法。 Google 傾向于主張使用 Systrace 類似的方法來查看丟幀率,他們有一個代碼庫,可以為你提供幾乎能直接工作的代碼(但不是很有效)。這允許你進行自動化性能測試,以查看丟幀率是否變化。

NimbleDroid 有一個免費的試用選項,你可以在其中上傳 APK,它將自動測試冷啟動,你也可以增加些應(yīng)用程序中的關(guān)鍵流程。他們提供一個函數(shù)發(fā)生的時間序列圖和詳細信息。它可以免費進行試用(例如上傳你的 APK 并獲得冷啟動時間,看是否有明顯問題)。如果你想使用它來進行回歸測試,那么它是很貴的,但它會幫助你意識到,有人做了一個改動,我們的啟動時間變慢了,或者我們的關(guān)鍵流程慢了。如果性能是一個高優(yōu)先級的目標,那么使用它是很有效的。

JSON

人們在考慮性能時往往都會想到 JSON。有很多的 JSON 庫。我的第一個警告是:人們喜歡純粹通過性能來看待 JSON 庫。這是一個錯誤。我收到了我最大的請求(150千字節(jié),30,000行,巨大的 JSON 文件)。我分別用 GSON 和 Jackson 解析了它們。它們相差大約 20 毫秒,對于那個巨大的文件來說,這并不瘋狂。

我的第一個建議是:更多地關(guān)注易于使用的東西,有很好的文檔的庫。你希望得到支持。你不用花幾個星期讓開發(fā)人員嘗試找出原因,就因為 stackoverflow 沒有答案。除非你對性能有超高的要求,GSON 和 Jackson 是使用最多的,最受歡迎的,特別是在 Android 上,GSON 更受歡迎。

Moshi 是 Square 采用的庫。它跟 GSON 非常相似。我試圖就如何使用好 GSON 給出了一些意見。你可以同意或不同意這些觀點,但都不會錯。

如果你關(guān)心 JSON 解析性能,并希望它更快,LoganSquare 是一個很好的選擇。它們在編譯的時候完成了其他庫需要在運行時完成的工作。與其他的庫相比,這將使你節(jié)約大約 1/4 的時間,或四倍的性能提升。如果你真的關(guān)心 JSON 性能,你不應(yīng)該使用 JSON。

相反,你可以使用 Flatbuffer。 JSON 人類可讀,F(xiàn)latbuffer 不是,但是因為這樣,它丟掉了其他的不需要的負擔。但是 Flatbuffer 與 JSON 相比,F(xiàn)albuffer 解析幾乎不花時間。Facebook 做了這個轉(zhuǎn)換。他們發(fā)現(xiàn)啟動時間增加了 10% 到 15%,啟動時間有所改善。他們也觀察到內(nèi)存使用效率更高。但是使用起來比 JSON 更難,所以謹慎使用。

數(shù)據(jù)庫 - SQL

對于數(shù)據(jù)庫,我們知道常見的是 SQLite - 標準 Android 庫。

SQLBrite 是 SQLite 上一個常見的簡單庫;它為你提供了數(shù)據(jù)庫的 reactive 接口。你可以監(jiān)聽你的用戶。如果你的用戶有任何更改,你會收到通知,你可以隨即更新用戶界面。這是一個非常小的庫。和 SQL 兼容的很干凈。

SQLDelight 也來自 Square。他們寫了很多庫。它試圖避免成為一個完整的 ORM,因為 ORM 會泄漏太多你的代碼,并且往往迫使你做太多的事情,當然它仍然試圖使數(shù)據(jù)庫的工作更容易些。它使得 API 類型安全,使得 SQL 語句組織的很好(它嘗試使其更容易些,同時不會太重)。

如果你愿意去做一個完整的 ORM,那么有很多很好的庫:GreenDAO,OrmLite,DBFlow 是一些比較受歡迎的( 還有許多其他選擇 )。他們都會說,它們在性能方便表現(xiàn)最好。每個庫都有些圖表,這些圖表顯示它們比其他的方案快 100 倍。我的建議是易用性是第一優(yōu)先事項,然后再考慮是他們在性能上是不是會更好。

數(shù)據(jù)庫 - NoSQL

Realm 是 NoSQL 的方法。它超級快。與其他可比較的數(shù)據(jù)庫不同,Realm 支持的文檔非常多。這可以最終節(jié)省你大量的開發(fā)時間,而且無所謂數(shù)據(jù)庫類型。

Google 推薦的另一種 NoSQL 方法是 LevelDB。鍵值對,但是它可以說是 “你能夠弄清楚該怎么做,但你必須自己弄清楚每一步”。 Realm db 可以幫助你避免這種情況。

Realm 數(shù)據(jù)庫需要特別注意的地方是它的大小( 我認為我們最初添加它時,我們的應(yīng)用程序大小增加了一倍 )。原因是它是一個本地庫。對于每個芯片架構(gòu),它們在你的應(yīng)用程序中都包含了 Realm 數(shù)據(jù)庫的完整副本。為了避免這種情況,你可以將此代碼放入 Gradle( 參見幻燈片中的代碼 ),并為每個架構(gòu)生成一個單獨的 APK。你把它分解成多少個版本,大小就會減少多少。這也會使你的內(nèi)存節(jié)省很多。對于任何本地運行的 C++ 代碼,這是正確的做法,所以在 Crashlytics 和其他一些受歡迎的庫中,你能看到同樣的收益。

還有另外一款很酷的 Google Play 商店的應(yīng)用程序 Native Lib。 - 它在 Play 商店中,它會顯示些本機庫,以便你可以看到你是否為你的 APK 下載了不適用于你手機的代碼庫。這樣做會減少內(nèi)存使用。如果你就是在尋找手機上保存數(shù)據(jù)的方案,你可能希望在手機上存儲數(shù)據(jù)。如果你正在構(gòu)建一次性的應(yīng)用程序,請不要保持數(shù)據(jù)。如果你正在使用 Realm 在存儲量很小的手機上構(gòu)建應(yīng)用(為什么在這種情況下你的應(yīng)用需要占用大量的存儲)?但總的來說,這是一個非常好的數(shù)據(jù)庫解決方案。

數(shù)據(jù)庫 - 移動平臺

另一個方面是移動平臺:移動開發(fā)人員的夢想,我們不再需要這些服務(wù)器指南。我們也可以自己構(gòu)建應(yīng)用程序。以前的 Parse 是最好的例子(可能會安息)。

現(xiàn)在移動平臺中最有名的就是 Firebase 和 Realm。它們都是 NoSQL 模型,它們有一些查詢方面的挑戰(zhàn),但是構(gòu)建速度非常非?臁7浅_m合進行同步更新。聊天是最常見的解決方案,你發(fā)送聊天消息,突然所有的手機都能獲取更新。不必構(gòu)建數(shù)據(jù)庫,不必擁有服務(wù)器,你可以使用其中一個解決方案。它使得構(gòu)建過程非常迅速,馬上完成應(yīng)用并推向市場。而且性能也特別好。

Realm 與 Firebase 的區(qū)別是它有離線優(yōu)先的優(yōu)點。它們都可以脫機,但是 Firebase 是事后補救,而 Realm 是事先就設(shè)計好了,Realm 在許多方面都支持離線。許多應(yīng)用程序幾乎不需要在線行為。如果你正在考慮運行應(yīng)用跟蹤程序,我們希望同步我們的運行狀態(tài),而且我們希望所有功能都能完全脫機運行,之后在線工作也正常。Realm 就會脫穎而出。

Analytics

我喜歡分析。精益創(chuàng)業(yè)的說法是。如果你可以測量它,你就可以優(yōu)化它。如果你沒有數(shù)字的東西,一切都是隨機的,你只能猜想如何使它更好。我喜歡有詳細的分析,來了解這個改變是否使事情變得更好?人們是否使用此功能?如何改善它?

Analytics 是封裝第三方庫的理想選擇。如果你封裝好了 Analytics,那么你應(yīng)該能夠在不修改任何功能代碼的前提下,完全替代你的分析服務(wù)。你應(yīng)該能夠很容易地添加一個新的 Analytics 服務(wù),以便它們能同時工作。封裝 Analytics 代碼是一個很好的實踐。

如果你正在添加分析數(shù)據(jù),最簡單的方法是記錄你的屏幕,記錄人們?yōu)g覽過的屏幕,將其放在抽象的 activity 中。這樣會很快地獲得很多的價值。

我看到人們使用 Analytics 技術(shù)的常見錯誤是增加了太多的 Analytics 。他們會在任何地方添加一千個事件,然后沒有人知道這個分析意味著什么。他們沒有進行充分的測試,所以你真實的注冊只有注冊的 2/3。在添加分析時需要非常小心。嘗試使用簡單的命名和標準。不要使用分析來延遲輕松的決定。如果有一個容易的決定,那么請開始。如果你的分析結(jié)果告訴你“人們不喜歡釋放內(nèi)存”,那先假設(shè)你的分析是錯誤的。得出一個錯誤的結(jié)論是很容易的。如果你有一個很重要的結(jié)論,首先要做的是確認你的分析代碼方面沒有什么瘋狂的事情。

Firebase

Firebase 曾經(jīng)是一個實時數(shù)據(jù)庫,然后 Google(混淆我們)開始使用一大堆叫做 Firebase 的工具。Firebase Analytics 是所有 Firebase 工具的基礎(chǔ)。Google 意識到 iOS 和 Android 開發(fā)人員正在解決同樣的問題。他們正在使用第三方服務(wù)并且通過付費來解決所有這些問題。他們認為,我們可以使構(gòu)建應(yīng)用程序更加容易,而且構(gòu)建應(yīng)用程序更容易,賺的錢就更多。他們做了這些工具的競品。迫使它們更好用,谷歌試圖使分析工具成為所有的工具的基礎(chǔ)。這樣做的愿景是,如果你收到崩潰報告,看到你的分析數(shù)據(jù),你可以按照崩潰的投資回報率給它們排序。你的通知系統(tǒng)也參與其中,你可以發(fā)送通知給那些碰到最昂貴的崩潰的客戶,并告訴他們一些免費的折扣。我們知道你即將購買,因為你是一個高價值的崩潰。

這是個很酷的愿景。還沒有實現(xiàn),實話實說。有些工作正常,有些還在開發(fā)中,這不是谷歌最高的優(yōu)先級的任務(wù)。但是很多工具還是很好的(不如競爭對手的工具)。 Analytics 雖然是免費的。但是事件不受限制。沒有太多的理由不使用它。

另一個流行的是 Google Analytics(分析)。它很容易地獲得許多關(guān)于用戶的基本信息。這是我看到的唯一一個提供很酷的行為流程圖的工具,在那里你可以看到人們在你的事件之間切換。它還是有點過時了,其記錄事件的風格比所有其他分析工具更舊。它也是免費的,F(xiàn)irebase 意在替換它。

A / B 測試

我個人認為 A / B 測試被過度宣傳。通常它被用于慢速學習,以便你了解的更清楚,如果是簡單的命名規(guī)則就不適用了,當然你可以將其投放到用戶手里,你會發(fā)現(xiàn),100 個用戶的樣本中,55% 偏好了這一選擇。這就是你通?吹降 A / B 測試。

它很容易產(chǎn)生 Bug。基本上,A / B 測試中應(yīng)用程序版本數(shù)是你應(yīng)用程序中的 A / B 測試數(shù)加 2。如果你的應(yīng)用程序中有 3 個 A / B 測試,那么就有 8 個不同版本應(yīng)用程序一起工作。你可能沒有測試各種不同版本的應(yīng)用程序。有時候你可能會發(fā)現(xiàn)因為這些問題,往往會導致重要的決定不太容易做了。

我的解決方案是用戶分析服務(wù)。 Mixpanel 具有非常好的 A / B 測試工具,而且和你的分析工具兼容。有許多工具用于 A / B 測試。我想說最有名的是 Optimizely 和 Apptomize。Optimizely 更適合網(wǎng)頁( 他們的價格 都有點神秘)。他們幫助你提供不同的版本,告訴你這是一個比另一個有顯著的更好的統(tǒng)計學差異的版本。

Firebase Remote Config 在技術(shù)上可以用來進行 A / B 測試。它不是用于 A / B 測試的。它是用來在不需要開發(fā)人員的更新的情況下,從服務(wù)器發(fā)送鍵值對的,但是這能讓我們做 A / B 測試。你可以發(fā)送兩個不同版本的鍵值對,然后你可以使用代碼來決定要做什么。之后,你可以將其傳遞到你自己的分析界面,并找出解析它的方法。從某個角度說,如果你使用 Firebase 遠程配置,你是在創(chuàng)造輪子。

你也可以使用 A / B 測試商店列表。這是值得嘗試的,特別是你在不同的國家里測試。這是比較容易的,你可以在那里獲得一些收獲。

崩潰報告

像分析一樣,有一千個解決方案。 我只打算介紹少數(shù)幾個

人們首先看到,特別是 Android 新手,那就是 Play 商店。每當你遇到崩潰時,你可以選擇發(fā)送報告。大家都會直接忽略,大約 1% 的崩潰出現(xiàn)在 Play 商店中。有時候,如果你的用戶數(shù)非常大,而且有些非常神秘的崩潰,那可能值得去看看,因為人們會對發(fā)生的事情發(fā)表評論。也就是說,你有 1% 的崩潰; “99% 的人說應(yīng)用很爛,崩潰”。但是每隔一段時間,就會有這樣的評論 “我在手機上旋轉(zhuǎn)了屏幕,它崩潰了”( 你好像是,啊,一個開發(fā)者,我很感激

Crashlytics 趨勢是最受歡迎的。這是 Twitter 的 Fabric Suite 或者說是現(xiàn)在的 Google Fabric Suite 的一部分。它是免費的,并為你提供一個非常好的,高級的,有組織的崩潰視圖。你仍然需要自行排序和確定優(yōu)先級。它有一些問題,很難搜索和查詢。我看到人們聯(lián)合使用 Bugsnag,這樣查詢和搜索會更好一點。 Bugsnag 是相當不錯的,但它不是免費的。

Instabug 和 Telescope。Telescope 是個庫。你把它放到 bug 里,作為第三方服務(wù)。這些庫的優(yōu)點不是監(jiān)控 crash,而是讓你在問題出現(xiàn)時,搖晃手機來報告問題。這樣,當你的團隊中的設(shè)計師看到錯誤時,他們不用在 JIRA 里提交 Bug,或者和別人說明所有的步驟然后讓別人來報 bug,但是你仍然希望這些不是 crash 的 bug 也能被修復(fù)。有這么一個工具,所有的測試用戶,alpha 用戶,你公司的人,看到錯誤都能告訴你,這些問題需要修復(fù)。

推送通知

作為開發(fā)人員,第一反應(yīng)是使用 GCM 或現(xiàn)在的 Firebase Cloud Messaging,這些庫正在重組。但是這些工具對營銷人員不友好。最簡單的情況是,如果你已經(jīng)有了很好的分析服務(wù),F(xiàn)irebase 和 Mixpanel(以及其他許多庫)都可以用來發(fā)送通知。你可以根據(jù)你的 activity 發(fā)送消息。可以這樣設(shè)計,一個從來沒有發(fā)生過購買的人,做了三次搜索,這時你可以給他們發(fā)送一個通知,建議他們買些東西。這是最簡單的情況。

有時你會想要一些更深入的東西。Urban Airship 的推送通知特別專業(yè),這是他們的主要方向。他們發(fā)現(xiàn),“人們只會看到通知的前 60 個字符”,我們都會收到這樣的通知,你只能看到前面幾個字。就像,“你不會相信這個…”,它被截斷了。然后你點擊它,你被帶到一個隨機的屏幕里,你甚至不知道推送通知的內(nèi)容是什么。Urban Airship 很好,他們幫助你思考這樣的事情,給你更多的細微差別提示,思考如何能更好地推出通知服務(wù)。

Kahuna 很受歡迎,有很多人都在使用它,但我會強烈反對。他們的想法很棒。通過借助 AI 來幫你確定哪種推送方式更合適,是發(fā)送電子郵件,還是發(fā)送短信或者是推送通知。AI 計算出最好的推送時間,并建議通知上需不需要添加花朵。這部分他們還沒有實現(xiàn)。但他們現(xiàn)在會做些文字上的變化。他們試圖讓通知受人喜愛,盡可能地推送最合適的通知,想法很酷,希望它能很快實現(xiàn)。但是現(xiàn)在,現(xiàn)實實現(xiàn)中,他們遇到了很多問題,用戶的通知被發(fā)送給錯誤的用戶。用戶被合并在一起,視為一組。所以使用時請小心。有些人用的很好。但我被坑了。

更輕松

有很多偉大的工具能使你的開發(fā)更容易些。

一個工具是 Butter Knife(@indVView)。它使你的代碼更漂亮。你可以使用 @BindView 通過 ID 查找視圖,而不必遍歷所有的視圖。Zelezny,是一個Android Studio 插件。把它放進 Layout 中,它會自動生成 BindViews 和 OnClicks。如果你以前一直是手敲代碼,它會節(jié)省點時間。最大的限制是 annotation 的處理會破壞增量編譯。如果你有 Butter Knife,那么你可能會比沒有 Butter Knife 時的增量編譯慢些。對我個人而言,我喜歡所有的 annotation 處理工具,船已航行。我已經(jīng)接受了 annotation 處理器打破我的增量編譯的現(xiàn)實。我聽說有人建議將它們?nèi)糠旁谕粋模塊中可以解決這個問題。這是唯一的缺點,許多 annotation 處理都會有這個問題。也許有一天這個問題會被修復(fù)。 JRebel 聲稱一些特定版本的增量編譯已經(jīng)修復(fù)了。除此之外,Butter Knife 是最好的選擇。

Hugo 是個 Jake Wharton 的庫(* 當我說 Jake Wharton,一半的時候是指 Square,它們是同一個意思*)。它是一個輕量級的庫,你可以在方法之上執(zhí)行 @Debug.Log,然后打印出該方法花費的時間,以及參數(shù)。它特別適用于現(xiàn)場性能記錄。 “我需要緩存這個變量嗎?它被調(diào)用太多了以至于變慢了嗎?”你可以看到,“不,這只花了 10 毫秒,我應(yīng)該把它放在一個后臺線程上,或者花了不到一毫秒,我們不用擔心這個”。它很容易納入你的代碼,并迅速獲得相關(guān)數(shù)字。

Dart & Henson,你有 intents ;不需要使用鍵值映射,它給你應(yīng)該有的值。它做了點 annotation 的映射來展示 intents 的值是什么。我更喜歡的另外一種理解方法是你正在調(diào)用的 activity 的靜態(tài) intents 。這樣,你可以傳入你想要的參數(shù),這樣就解決了神秘的鍵值對的問題。它使得代碼更加緊密,這樣可以防止錯誤。

如果你喜歡 lambdas,你應(yīng)該使用 Retrolambda。需要注意是它產(chǎn)生四種方法,而不是正常的匿名類。我認為使用 Retrolambda 會使得代碼不易讀,這是你必須做出明智決定的地方。

更困難(初期)

我們來談一談哪些庫會讓開發(fā)變得更加困難,或者說開始的時候更困難。但總的來說,這些都是好工具。

RxJava

RxJava,對于那些沒有聽說過的人來說,這個庫的想法是,過去的代碼從 A 點開始,到 B 點結(jié)束。但在 Android 世界中,移動開發(fā)世界中,這一切就都不一樣了。 *你從 A 點開始。然后人們點擊某些東西,所以你必須做些別的事情來響應(yīng)。然后一個通知進來,你必須又做些事情。然后數(shù)據(jù)庫請求出現(xiàn)了。Reactive 努力使你的代碼能夠?qū)δ愕膽?yīng)用程序中的發(fā)生的事情做出反應(yīng),幫助你更好的組織它們,而且方便移動。

起初很難,因為它有一個學習曲線。如果你正在看代碼,特別是對于沒有接觸過 RxJava 的人來說,會有許多不清楚的地方。最簡單的就是網(wǎng)絡(luò)。但是,如果你有幾個標準的例子,你使用這些案例,并確保是最佳的做法,情況就會不一樣了。當你開始擁有這些功能時,它們非常強大,你可以將其運用于應(yīng)用程序中的任何地方,但是當你這樣做的時候,每當雇用新的開發(fā)人員,你將不得不教會他們每個 activity 是怎么工作的,這需要很小心。

此外,它很容易用錯。即使是關(guān)于 RxJava 的許多會議都會漏掉一些最佳做法。例如,如果你不取消訂閱網(wǎng)絡(luò)呼叫,那么你會被回調(diào),這時可能會發(fā)生崩潰,因為屏幕已經(jīng)不存在了。謹慎地使用它,總體上來說它還是很好的。

Kotlin

當我說小心使用非內(nèi)建語言或者說新語言不尋常的地方時,我想說的就是那些你能看到的不尋常的地方。 Kotlin 生成了更整潔的代碼。這有好處。使你的代碼更容易閱讀,也會使沒有意義的東西少一些,這是你需要的核心東西。它也隱藏了指針的概念。

最大的缺點是它會隨機地破壞事情,如果有什么事情發(fā)生,你都會懷疑 Kotlin。這可能是 Kotlin 的錯,可能不是,但是都會花掉開發(fā)人員的許多時間,來弄清楚到底是不是 Kotlin 的錯。你需要更新 Gradle 的構(gòu)建,然而這依舊不奏效。這可能是 Kotlin 的錯,也可能不是 Kotlin 的錯,但是你都不得不重新檢查 Kotlin。

同樣的情況是,你的 Android Studio 也會隨機崩潰,或者 ProGuard 不工作了,因為它去掉了一些 Kotlin 的類。這些事情經(jīng)常發(fā)生,很難扭轉(zhuǎn)。Kotlin 有很多權(quán)衡點。我們在代碼中使用它。確實有一些問題,與此同時,了解 Kotlin 的人們的代碼審查更快。對于不知道 Kotlin 的人來說,有一個學習的曲線。這是一個權(quán)衡。你必須自己決定。

相機

如果你曾經(jīng)在 Android 中使用過 Camera,而且你采用的是原生的方案,這并不瘋狂,你會發(fā)現(xiàn)有攝像頭 one API 和攝像頭 two API,而且攝像頭 two API 沒有比攝像頭 one API 更好,如果你同時支持新舊設(shè)備,你必須使用攝像頭 one API,除非你只打算在非常新的設(shè)備上正常運行。我的第一個建議是,如果你有使用相機的場景,構(gòu)建一個 intent。讓其他人的相機應(yīng)用來解決你的問題,如果這不是你的核心場景的話。

如果不是這種情況,有一個名為 Material Camera 的庫,我以前 fork 過。你可以添加自己的外觀。它幫助你創(chuàng)建相機。解決問題。但是當你按照本教程進行首次設(shè)置后,橫向顯示時,圖片會顛倒,你不得不在每個手機上都進行測試,因為他們會以不同的方式安裝相機。還有很多邊界案例要考慮。Material Camera 是偉大的,它已經(jīng)把這些情況都解決了。它也支持視頻。這是視頻模式。你可以改變它上面的 UI,效果很好。再說一次,如果 Camera 是你非常核心的用例,那么你應(yīng)該重新構(gòu)建它,這只是個折衷的方案。

我使用的每個相機應(yīng)用都有裁剪功能,這個功能很可怕。我不知道是什么原因。你試圖剪裁,突然間你的視頻被剪掉了中間部分。有一個很好的庫叫做 “Android Crop”。它提供了一個非常簡單的新的 activity 來完成剪裁。

全球思考

作為 Android 的開發(fā)人員,我們需要考慮到世界各地的所有開發(fā)者。如果你正在為世界各地的開發(fā)人員做些開發(fā)工作,有些事情你必須考慮,比如網(wǎng)絡(luò)仿真:你希望能夠在低質(zhì)量網(wǎng)絡(luò)上進行測試。Android 上做到這點比 iOS 難。仿真器技術(shù)可以提供本地仿真器 AVD,但通常情況下,我的經(jīng)驗是,如果你在模擬器上進行任何 3G 操作,沒有應(yīng)用工作正常。我的一些應(yīng)用程序有時候能在 3G 上正常工作。

我知道的最成功的工具是 Charles 代理。你可以配置經(jīng)過某個代理。這很容易設(shè)置。你可以告訴代理,下載速度應(yīng)該是多快。但仍然有一個挑戰(zhàn),你需要知道網(wǎng)絡(luò)可能有多快。比如說像巴西的 3G 網(wǎng)絡(luò),幾乎是一個無意義的聲明 - 3G 在巴西各處都不一樣,在各地都是非常不同的。某些時候,你必須嘗試找一些數(shù)字,選擇一些數(shù)字。

外面有些資源,但是選擇參數(shù)是挑選網(wǎng)絡(luò)仿真最困難的部分之一。有一個名為 Augmented Traffic Control 工具,它來自 Facebook。它允許你連接到服務(wù)器或設(shè)置路由器,你可以設(shè)置配置文件 - 當你連接到路由器時,你的互聯(lián)網(wǎng)應(yīng)該有多快。如果你有非開發(fā)人員為你測試,他們?nèi)匀豢梢赃B接到這個 WiFi 網(wǎng)絡(luò)并設(shè)置他們擁有的連接級別。產(chǎn)品經(jīng)理和測試人員一般也應(yīng)該考慮質(zhì)量較差的網(wǎng)絡(luò)。 ATC 服務(wù)器很好用。

我相信新的 Android O 暗示他們會有類似于 AutoFitTextView 的東西,但現(xiàn)在這只是一個庫,只要文本對于文本框來說太大,文本就會縮小。如果你正在翻譯德語,它的很多字母比英文還是要大一些,那么它會把它縮小到框中。這不是你的第一個翻譯解決方案,但最好讓它們縮小到文本框的大小,而不是填滿整個屏幕并覆蓋所有內(nèi)容。它將調(diào)整你的文本大。ǜ哪愕奈谋敬笮磉m應(yīng)),這是一個很好的安全的翻譯。

YearClass 是 Facebook 的另一個庫。它會告訴你,運行你產(chǎn)品的最新的手機生產(chǎn)年份是多少。如果我們說 2015 年是最高的年份,那你就不用關(guān)心 2016 年制作的手機上的一些特別的事情。從分析角度來說,這是最好的 - 比如這個崩潰是,發(fā)生在 Android OS Marshmallow 上,所有的手機都是低功耗的手機,有時候會發(fā)生這種情況。知道一下 crash 在不同年份的手機上的發(fā)生概率可以幫你對這個 crash 有更深的了解。

Connection 類是理解用戶連接質(zhì)量的一個非常好的工具(* 這是我在開始時推薦的封裝樣本類)。它對網(wǎng)絡(luò)進行分類。不是分成 4G 3G,因為它們變化很大,它依據(jù)的是帶寬,分為優(yōu)秀,好,中度或差,或未知。它通過采樣下載速度來分類。然后它會移動平均值。這樣做的價值是,例如,你是一個顯示許多圖像的圖像網(wǎng)站,你可能希望在較差的網(wǎng)絡(luò)上降低圖像質(zhì)量,或著執(zhí)行其他操作。預(yù)先知道帶寬可以做許多事情。

最大的警告是它的抽樣可能是不合時宜的。你能做的事情是讓它們開始采樣和停止采樣。比如,當我打開應(yīng)用程序時,開始采樣,當我關(guān)閉應(yīng)用程序時停止。它們做的事情是查看你下載的數(shù)據(jù)量,每秒刷新一次。如果用戶將你的應(yīng)用程序打開,并且沒有進行任何操作,他們會認為你的網(wǎng)絡(luò)慢的可怕。我們所做的是,你可以在網(wǎng)絡(luò)調(diào)用或者圖像調(diào)用的中間啟動它,這樣做的效果很好。除此之外,這個庫對你的網(wǎng)絡(luò)帶寬了解的很準確。

About the content

This content has been published here with the express permission of the author.

 

 

來自:https://academy.realm.io/cn/posts/tools-and-libraries-for-common-android-problems/

 

標簽: Google 安全 代碼 電子郵件 服務(wù)器 谷歌 互聯(lián)網(wǎng) 開發(fā)者 權(quán)限 數(shù)據(jù)庫 搜索 網(wǎng)絡(luò) 移動平臺

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:Google S2 中的四叉樹求 LCA 最近公共祖先

下一篇:Ruby Web 服務(wù)器的并發(fā)模型與性能