最新のAndroidアプリケヌションを䜜成するためのヒント。 ダンデックス講矩

2017幎のモバむル開発孊校の資料は匕き続き公開されたす。 次に、Yandex.MailチヌムのAndroid開発者Dmitry Nikitinによる倧芏暡な講矩です。 Dmitryは、倚くのラむブラリで迷子にならないようにれロからプロゞェクトの䜜成にアプロヌチする方法ず、1぀たたは別の゜リュヌションを遞択するずきに䜕を探すべきかを指瀺したす。





-みなさんは、少なくずも2〜3か月はAndroidをプログラミングしおいたす。 おそらく、誰かが数幎前からプログラミングをしおいお、developer.android.comを最初から最埌たで読んでいるのでしょう。 たたはそうでないかもしれたせん。 しかし、少なくずも1぀の方法で倚くのこずを実行する方法をご存知でしょう。 しかし、これらの方法の倚くがあり、各チヌムが独自の方法を持぀こずができるこずは秘密ではありたせん。倚くの堎合、この方法たたはその方法は歎史的な理由だけで遞択されたす。



今日は、どのような遞択肢ず開発ツヌルがあり、ラむブラリを遞択する際に䜕を匷調すべきかに぀いお簡単に説明したいず思いたす。



今日はどのツヌルに぀いおお話したすか たず第䞀に、アプリケヌションの即時機胜を実装するのに圹立぀ものに぀いおこれは、プロゞェクトマネヌゞャヌが通垞私たちに通垞芁求するものです。



第二に、それはコヌドの品質を制埡し、より柔軟で拡匵可胜にするのに圹立ちたす。 そしお、開発にも関連しおいるものの、前の2぀のポむントに盎接関連しおいないものを怜蚎したす。







このツヌルは、速床ず消費されたRAMずディスクメモリの点でどれほど効果的ですか。



どちらが良いか、どれが悪いかをどのように遞択したすか たず、䜿いやすさ、このツヌルを䜿甚しお特定の問題を解決するのがどれほど簡単かを芋おいきたす。



原則ずしお、よく知られおいるラむブラリはすでにテストでカバヌされおおり、統合されるずバグがより頻繁に発生するため、クラむアントコヌドが簡朔で単玔であればあるほど、ミスをする可胜性は䜎くなりたす。



䞀方、最も盎接的なビゞネスロゞックではない堎合があるため、特定の䜕かが必芁になる堎合がありたす。ここで、遞択したツヌルが束葉杖なしでこれを実行できるほど柔軟性がある堎合、これは倧きなプラスになりたす。



以䞋の基準は倖郚ラむブラリのみに適甚されたす-これはラむセンスです。 倚くの堎合、商甚コヌドを蚘述するため、ラむセンスは゜フトりェアの䜿甚を蚱可するだけでなく、゜ヌスの開瀺を匷制するものでもありたせん。



最も人気のあるラむセンスはApache 2.0ずMITです。 原則ずしお、それらは抂しお、私たちに制限を課したせん。 他のラむセンスは泚意しお䜿甚する必芁がありたす。



さらに、接続するために必芁なものはすべお、Android SDKず共にではなく、JCenterたたはMavenセントラルのどこかに眮いおある堎合は、既にコンパむルおよび配垃されおいるこずが望たしいです。



䞍明な点がある堎合は、ドキュメントを参照するか、この補品をサポヌトしおいる人に質問するこずができたす。



そしお、最埌の項目は順番に䞊んでいたすが、重芁床には関係ありたせん-これは、このツヌルが倚くのメ゜ッドをどの皋床もたらすかです。







なぜこれが重芁なのですか アプリケヌションがLollypop未満のAPIをサポヌトしおいる堎合これがアプリケヌションの倧郚分です、これらのデバむスではコヌドがDalvik仮想マシンで実行され、APKのビルド時にJavaファむルがバむトコヌドにコンパむルされおからDalvik実行可胜ファむルにパックされたす。 このようなファむルにはそれぞれ65,000を超えるメ゜ッドを含めるこずはできたせん。この制限に達するず、アセンブリ䞭にこのような゚ラヌが発生したす。









同時にいる方法は 良い方法では、どのクラスが占有されおいるかを远跡し、䞍必芁なこずを避けるようにする必芁がありたす。 ぀たり、これがもたらすメ゜ッドの数に関しお、この䟝存性たたはその䟝存性がどのような肯定的な貢献をもたらすかを垞に評䟡する必芁がありたす。



たずえば、カヌ゜ルを安党に閉じるためだけにGuavaを䜿甚する堎合、ナヌティリティメ゜ッドを蚘述し、そのような倧きな䟝存関係を攟棄する必芁がありたす。



テストでほずんどの郚分に䜕かが䜿甚されおいる堎合、プロゞェクトに盎接含たれないように、この䟝存関係をテストコンパむルに远加できたす。



たた、ラムダ匏や参照メ゜ッドなど、さたざたな構文糖のコストが高いこずにも泚意する必芁がありたす。 このトピックの詳现に぀いおは、Jake Wharton のクラスレポヌト、Exploring Hidden Java Costsをご芧ください。



ラムダに加えお、他の生成されたコヌドを芋るこずが重芁です。 たずえば、1぀のバヌゞョンから始たるバタヌナむフでは、メ゜ッドの生成が40少なくなりたした。







プロゞェクトが占めるクラスの数を远跡するにはどうすればよいですか これには、Dexcountプラグむンが適しおいたす。 誰がいく぀のメ゜ッドを持ち蟌んだのかがわかるように、このような矎しいチャヌトが生成されたす。



䞭毒を远加する前に、 methodscount.comサむトの費甚がどれくらいかかるかを評䟡できたす。 たた、掚移的な䟝存関係がもたらすメ゜ッドの数も確認できたす。



他のすべおが倱敗した堎合でも、いく぀かのdexファむルを䜿甚できたすが、远加の問題が発生したす。 このようなアプリケヌションは通垞、起動時間が長くなり、より倚くのメモリを消費するずいう事実に加えお、堎合によっおはクラッシュするこずもありたす。 MultiDexを䜿甚しお構築する堎合、アプリケヌションを正垞に起動しおプラむマリdexファむルに配眮するために必芁なクラスの分析が実行されたす。



たずえば、ネむティブコヌドから呌び出しが行われるなど、䟝存関係が耇雑な堎合、そのようなクラスは他のdexファむルに分類され、起動時にNoClassDefFoundErrorが発生したす。 これを回避するために、別の構成でそのようなクラスを指定する必芁がありたす。



さらに、この分析によりビルドの速床が倧幅に䜎䞋したす。Lollypopバヌゞョンから、DalvikはAndroidランタむムに眮き換えられたした。Androidランタむムは既にMultiDexをサポヌトしおおり、SDK 21のビルドははるかに高速です。







したがっお、ハックずしお、SDKの実際の最小バヌゞョンがはるかに小さいずいう事実にもかかわらず、ロヌカルアセンブリに察しお21のバヌゞョンを指定するずいう事実を利甚できたす。







スタゞオのコマンドラむンパラメヌタからこの倀を取埗したす。これにより、ロヌカルでより速く収集する機䌚が埗られたす。 同時に、スタゞオ内のAPIレベルのテヌプチェックは壊れたせん。



たずめるず。 メ゜ッドの数で䜕をする必芁がありたすか 健康な人の方法は、それらを自然に数え、枛らすこずです。 たた、proguardを䜿甚しお、接続したが䜿甚しおいないものを削陀するこずもできたす。 リリヌスコレクションには、すでにproguardが含たれおいるため、デバッグでのみMultiDexを有効にする必芁がある堎合は、通垞の方法です。 しかし、他のすべおが倱敗した堎合、MultiDexをオンにするだけで、迅速なロヌカルアセンブリであなたの人生をわずかに明るくしたす。



アプリケヌションで通垞行う必芁があるタスクは䜕ですか 倚くの堎合、サヌバヌからデヌタを受信し、特定の方法で凊理し、画面に衚瀺したす。たずえば、オフラむンで䜜業する必芁がある堎合は、特定の方法で保存する必芁がありたす。 たずえば、デヌタベヌス、共有蚭定たたはファむル。



GitHubからのナヌザヌデヌタを衚瀺するサンプルアプリケヌションを䜿甚しお、これらすべおのステップを芋おみたしょう。



ナヌザヌデヌタ自䜓はサヌバヌ䞊にあり、そこから取埗する必芁がありたす。 どうすればこれができたすか たずえば、HttpUrlConnectionがありたす。







StackOverflowに移動し、get-requestの䟋を取り䞊げお、URLを眮き換えたす。 接続を開きたす。 InputStreamを取埗したす。 ここで必芁なデヌタを文字列ずしお読み取りたす。 接続を閉じるこずを忘れないでください。 このリク゚ストでは、すべおが簡単です。 たずえば、ファむルをReadMeでサヌバヌにアップロヌドするなど、ささいなこずをする必芁がある堎合は、問題が始たりたす。 これを行うには、独自のラッパヌを䜜成する必芁がありたす。







そしお、すでにこのサむズですが、タスクはそれほど珍しくないように思えたす。



たた、このためのテストを䜜成する必芁がありたすが、実際には、他の誰かのコヌドに察しおは行いたくありたせん。



HttpUrlConnectionの䞊で動䜜する倚くのラむブラリがありたす。この堎合、送信ファむルは単玔化され、非同期呌び出しなどの他の機胜が远加されたす。



たずえば、Kevin SavinskiのHttpClientラむブラリがありたす。 しかし、箱から出しおすぐにこれらすべおの欠点がない代替がありたす-これはOkHttpです。







OkHttpを䜿甚した同じファむルアップロヌドは次のようになりたす。 URLを提䟛するだけです。 RequestBodyを䜜成したす。 そしお、私たちは芁求を満たしたす。



Kitkat以降、ネットワヌクレベルのHttpUrlConnection自䜓はOkHttpを䜿甚したす。 したがっお、このオプションを遞択した堎合、Androidの異なるバヌゞョンではラむブラリの動䜜が異なるずいう事実から保護されたす。



そしお、リク゚ストの䞀郚にuseragentを远加したり、リダむレクトの堎合の動䜜を倉曎したりする堎合を想像しおください。 たた、OkHttpむンタヌセプタヌを䜿甚しおこれをかなり迅速に行うこずもできたす。







むンタヌセプトメ゜ッドを再定矩したす。 元のリク゚ストを取埗したす。 䜕らかの方法でそれを倉曎し、チェヌンのさらに䞋に枡すこずができたす。 そしお、このむンタヌセプタヌをクラむアントに远加したす。 同時に、リダむレクトの堎合にリク゚ストを繰り返しむンタヌセプトする堎合、addInterceptorではなくaddNetworkInterceptorを呌び出すこずができたす。



さらに、OkHttpは芁求を非同期的に実行し、Web゜ケットを操䜜し、他の倚くの優れた機胜を実行できたす。







ただし、欠点が1぀ありたす。 それにもかかわらず、それはサヌドパヌティのラむブラリであり、2,500のメ゜ッドを描画したす。 これから私たちを救う組み蟌み゜リュヌションはありたすか



Androidの倜明けにはApacheHttpClientがあり、以前のバヌゞョンではより安定しおいたしたが、GoogleチヌムはAPIが今埌の開発には倧きすぎるず刀断し、廃止されるこずを宣蚀したした。







useLibrary“ org.apache.http.legacy”を明瀺的に指定しお、プロゞェクトで䜿甚するこずはできたすが、APKに既にパッケヌゞ化されおいるため、目暙を達成できたせん。







怜蚎されおいるオプションに加えお、GoogleがサポヌトするVoleyラむブラリもありたす。 以前の遞択肢よりも高いレベルです。 OkHttpがリク゚ストを非同期に実行できるように。 圌女は優れた内郚キャッシュを備えおおり、画像のアップロヌド方法も知っおいたす。これだけのために、imageviewはネットワヌクimageviewを継承する必芁がありたすが、これは非垞に匷い制限です。



残念ながら、VoleyはJCenterおよびMaven Centralにそれを配眮せず、゜ヌスコヌドず共にプロゞェクトにむンポヌトされたす。運が悪ければ、この゜ヌスコヌドも同じコミットで倉曎されたすが、これは非垞に悪いこずです。



Voleyは、同じOkHttpずは異なり、優れたドキュメントを自慢できたせん。







それで、私たちは䜕を取るべきですか メ゜ッドの数に厳密な制限がある堎合、たたはネットワヌクでの䜜業がそれほど耇雑ではないため、いく぀かの重芁なこずが必芁な堎合は、HttpUrlConnectionたたはそのラッパヌを䜿甚できたす。 それ以倖の堎合、OkHttpが最適なオプションのようです。 質問ず回答に぀いおは、ビデオを参照しおください-玄゚ド。



デヌタをダりンロヌドするこずになりたした。 これはJSON文字列です。 そしお今、Javaの芳点からどのように䟿利なビュヌを取埗できたすか







十分なデヌタがない堎合は、組み蟌みのJSONObjectを䜿甚しお必芁な倀を取埗できたす。 興味のある分野に出䌚うたで、構造党䜓を順番に回りたす。 倀を読み取り、次に進みたす。



倧量のデヌタがある堎合、このルヌチン䜜業を維持するのが難しくなり、特定のラむブラリを䜿甚するのが理にかなっおいたす。







たずえば、元々Android甚に䜜成されたSquareのMoshiがありたす。これにより、メモリ消費がより経枈的になりたす。 しかし、圌はかなり遅いです。



GoogleのGsonもありたすが、高速ですが、RAMをより倚く消費したすが、メ゜ッドの数の点では倚少魅力的です。



そしお、ゞャク゜ンがいたす。これは、リフレクションのカりンタヌパヌトの䞭で最速です。 圌は、ストリヌミングパヌトず盎接マッピング甚のDatabingを別々に持っおいたす。 しかし、同時に圌は倪っおいる。



さらに、コンパむル時に解析するためのアダプタヌを生成するLoganSquare GitHubぞのリンク がありたす。 JacksonストリヌミングAPIを䜿甚し、コンパむル時間の生成により、競合他瀟の速床を倧幅に䞊回りたす。







比范は、䜜成者のベンチマヌクで確認できたす。 提瀺されたオプションのLoganSquareが最速であるこずがわかりたす。







ただし、コンパむル時の生成では、構造に特定の制限が課されたす。 ゚ンティティ自䜓は䜕も継承できたせん。 ゞェネリックにも問題がありたす。



Instagramからのリフレクションのない別のパヌサヌ、IgJsonParcerがありたす。 圌はすべおのフィヌルドに盎接泚釈を付けるこずを矩務付けおおり、それを凊理する必芁がありたす。 このラむブラリにはただ安定したバヌゞョンがありたせん。たた、GuavaずApache Commonsの䞡方に䟝存しおいるため、メ゜ッドの数に問題がありたす。



したがっお、提瀺された゜リュヌションの䞭で、最速はLoganSquareであり、速床が非垞に重芁な堎合は、それを䜿甚できたす。 それ以倖の堎合は、速床、メモリ消費、たたはメ゜ッドの数がさらに必芁であるずいう事実に基づいお、以前のオプションから遞択したす。







救枈策を遞択したした。 テストするこずを忘れないでください。解析はテスト駆動開発に非垞に適しおいたす。 ドキュメントからJSONをコピヌし、テストを䜜成しおから、テストが緑色になるたで解析自䜓を䜜成したす。



倚くの堎合、远加のフィヌルドをAPIに远加できたす。



解析が倱敗するのを防ぐために、事前にテストで䞍明なフィヌルドを远加できたす。 したがっお、私たちはそのような倉曎の準備ができおいるこずが保蚌されおいたす。







反察に、デヌタをサヌバヌに送信するか、文字列ずしお保存する堎合は、逆のプロセス-シリアル化が必芁です。テストはその正確性を怜蚌するのにも圹立ちたす。



たずえば、ここではJsonUnitラむブラリヌが䜿甚されたす。 このような比范は順序やむンデントなどに察しお䞍安定であるため、裞線を比范しないように䜿甚されたした。そしお、取埗した倀を盎接比范したす。



そのため、Retrofitラむブラリ GitHubぞのリンク を䜿甚しお、オンラむンにする方法、解析する方法、これを組み合わせる方法を遞択したした。







したがっお、ベヌスURLを蚭定する単䞀のアクセスポむントがありたす。 その堎合、たずえばQA環境の堎合、ここですばやく倉曎できたす。 Moshi、Gson、Jackson、たたはProtobufからコンバヌタヌを遞択できたす。 そしお、私たちが電話をかける方法。 これは同期的に実行できたす。







たたは非同期で。







たたは、Rxを䜿甚したす。 これを行うには、APIメ゜ッドが単䞀の完了可胜たたは監芖可胜を返すこずを瀺す必芁がありたす。 そしお、適切なCallFactoryを遞択したす。







ナヌザヌデヌタの逆シリアル化に取り組みたした。 Javaでそれらをどのように玹介したすか







このようにするこずができたす。 しかし、䜕が悪いのでしょうか 将来、ログむンフィヌルドがコヌル䞭に盎接蚈算されるか、これらすべおのコヌルを蚘録するずしたす。



したがっお、可芖性をプラむベヌトに倉曎し、ゲッタヌずセッタヌを远加したす。











HashMapに远加する堎合は、equalsずhashCodeが必芁です。











ここに文字列に矎しいを远加したす。 たた、意図しお別のアクティビティに転送したり、画面が反転したずきにバンドルで保存したりする堎合は、このオブゞェクトをParcelableにする必芁がありたす。



そしお、新しいフィヌルドがクラスに远加されおいるこずを知るず、これらの円を繰り返し、䜕も忘れないようにする必芁がありたす。 幞いなこずに、この問題を解決できるラむブラリがありたす。







たずえば、AutoValue GitHubぞのリンク 。 AutoValueアノテヌションず抜象フィヌルドアクセスメ゜ッドを䜜成しおいたす。 フィヌルド自䜓は、アセンブリ䞭にラむブラリによっお生成されたす。 たた、前にリストしたこれらすべおのメ゜ッドを生成したす。



AutoValueのキラヌ機胜は、拡匵機胜を䜿甚するのに十分簡単であるこずです。 たずえば、コンパむル時アダプタヌを生成できるGsonおよびJackson拡匵機胜があり、これにより、同じLoganSquareの速床をキャッチできたす。 したがっお、1぀の石で2矜の鳥を殺したす。解析ずモデルの内郚衚珟の䞡方の問題を解決したす。



AutoValue Parcel拡匵機胜もありたす。 接続するず、Parcelableの実装を蚘述するだけで、解析をサポヌトするメ゜ッドが生成されたす。 さらに、クラスのフィヌルドの1぀がシリアル化可胜でない堎合、コンパむル䞭に゚ラヌが発生したす。







別のAutoValue拡匵機胜もありたす-Auto-Parcelも解析したすが、AutoValue Parcelずは異なり、オブゞェクトがランタむムで排他的にシリアル化されるこずをチェックし、あたり人気のないEPL 1.0ラむセンスも持っおいたす。



AutoValueに代わるものがありたす-これは䞍倉です。 MoshiおよびGson甚のアダプタヌもありたすが、Parcelable甚の拡匵機胜はありたせん。



そしお、他ずは異なり、盞続人を生成せず、元のクラスを眮き換えるLombokがありたす。



このすべおの魔法をサポヌトするには、IDEプラグむンず忍耐が必芁です。これはすべお非垞にバグが倚いためです。



したがっお、考慮されるオプションの䞭で、AutoValueずそのAuto-Parcel拡匵機胜が最も有益に芋えたす。 質問ず回答に぀いおは、ビデオを参照しおください-玄゚ド。



ナヌザヌの幎霢に応じおさたざたな皮類のバナヌを衚瀺する必芁があるずしたす。 すべおがシンプルなようです。 珟圚の日付を取埗し、生幎月日を蚈算しお幎霢を取埗したす。







しかし、Javaの日付ずカレンダヌを暙準ずしお䜿甚する堎合、驚きを期埅する必芁がありたす。 たずえば、getYearを呌び出すず䜕が埗られたすか 正解は117幎です。1幎ではないからです。



それはちょうど1幎ではないからです。







たた、Java.docからわかるように、これは1900幎から1幎埌です。Java.docを事前に読んでいないこずを非難するこずも䞀郚ありたす。



たたは、たずえば、GetInstanceカレンダヌの最も有名なメ゜ッドが実際に毎回新しいカレンダヌを䜜成するこずは、最も明癜なポむントではありたせん。







最も人気のあるJavaラむブラリの1぀はJodaTime GitHubぞのリンク です。 これを䜿甚するず、ナヌザヌの問題を簡単に解決できたす。 たずえば、新幎たでの日数を蚈算するこずもできたす。



さらに、JodaTimeにはTzdataファむルの最新バヌゞョンが含たれおいたす。 このファむルには、さたざたな地域のタむムゟヌンが時間ずずもにどのように倉化したか、およびUTCに基づいお珟地時間を取埗する方法の履歎が含たれおいたす。



このファむルは、おそらく山党䜓の゜リュヌションをカプセル化したす。 トム・スコットのビデオからそれらに぀いおさらに孊ぶこずができたす。 Tzdataファむルもシステム自䜓にありたすが、APKに埋め蟌む堎合、ベンダヌが叀いデバむスの曎新をリリヌスしない堎合、問題から身を守りたす。 代わりに、たずえば、ベンダヌは、HTCがよく行うように、新しい顧客向けに矎しい3次元タむムゟヌン遞択モデルを䜜成できたす。







しかし、APKにTzdataファむルを含めるこずは無駄ではありたせん。サむズが増加しおいるずいう事実に加えお、最倧5 MBのRAMを倧量に消費し始めおいたす。ダンルヌは 4幎前にこれに気付きたした。ラむブラリはJava専甚であり、このファむルにアクセスするずきにClassLoader.getResourceAsStreamを䜿甚するず、このような倧量のデヌタをキャッシュするだけでした。



圌はこの呌び出しをAssetManagerの䜿甚に眮き換え、Joda Time Androidず呌ばれるラむブラリをリリヌスしたした。







JDK , Java - , , Joda Time JSR 310. API Android , back-port ThreeTenBP, , ThreeTenABP, « » Tzdata.







たずめるず。 ? APK, API. ThreeTenABP , Joda Time - Android , , .



, .







UI- , AsyncTask. ? , , - .







Picasso. , placeholders, , .



, , , , URL, . Picasso .







Glide, Picasso , , .







Fetcher, URL, .







, Glide . StreamModelLoader, .







Loader Module, Module Manifest, , . , , . proguard.







, Glide, .



, activity , Glide , , .







, Glide , , ImageView . Picasso, , .



Glide .



Universal ImageLoader, , , deprecated.



Fresco, ashmem, , .



gif. , Glide.







, ? , , , , Picasso. - gif, Glide. Picasso Glide , API. ( . — . .)



? , dependency injection, MVP, MVVM . .







dependency injection, reflection-based RoboGuice, , , , . . Java , , , , reflection , Android , , .



RoboGuice deprecated. - Dagger1, , reflection , , . Dagger2. , .



, , . , - scope, . Toothpick, , , , . reflection free, scope. , , .







Dagger, . ( GitHub .)







, RoboGuice .







, , . , , , API, TootPick . — , .



MVP MVVM , , , , , , , , . , . , - .







. , , , . , GreenDAO, ORMLite NoSQL Realm.



, — .



, , . , , - , .



, SQLDelight, Java- SQL-. , , , , Rx, , StorIO SQLBrite.



Room, , , , , .



, ? , , -, . , — .







— checkstyle ( SourceForge ). , , . Override , , , , . . .







checkstyle, . , , .







, , , , , , .







. Java-.







Lint, Android- , , , .







. , nullability, , , , , , .







. baseline. Lint . , , .







Lint. .







XML.







— PMD ( SourceForge ). Java. .







.







.







, PMD, Java-, -. FindBugs ( SourceForge ). , , .







, , . , hashCode, , . ?



FindBugs , hashCode int, - abs , IndexOutOfBounds.







, , FindBugs .







FindBugs. , XML, HTML-, , , .







- , Findbugs:annotations.



, FindBugs , SpotBugs, , , Android, .







, , , , , dashboard. dashboard .







.







, -.







たずめるず。 ? — . , , , . ( GitHub .)







, , , ? JitPack, , - fork, .







— Kotlin. Google , , . NullPointerException ClassCastException. data-, , , AutoValue, , . — , Parcelable.



pattern matching, . , , Kotlin , , proguard .



, final everywhere, final, . Mockito — , . — — Mockito 2.



any. , matcher, null Mockito. Kotlin- null, . Mockito Kotlin. , Spek — JetBrains. , , Roboelectric. — Detekt SonarQube. これで私はすべおを持っおいたす。 ご枅聎ありがずうございたした。



著者の連絡先メヌル、電報



All Articles