経験豊富な開発者なら誰でも、彼らの最高のコードは彼らが書いたコードではないと言うでしょう。それは彼らが他の誰かの仕事から取ったコードです。
はい、私たち開発者は革新的な問題解決者ですが、私たちが遭遇する問題の多くはすでに解決されており、誰でも利用できるライブラリにパッケージ化された救済策があります。フリーホイールがいたるところにあるのに、なぜホイールを再発明するのですか?
Androidも例外ではありません。コードの再利用の究極のソースはAndroidSDK自体です。これには、多くの作業を行うための優れた構造とサービスが付属しています。
しかし、SDKが不足している場合、 Androidコミュニティ は、コーディング作業を大幅に節約できる最高級のライブラリをいくつか作成し、高度に調整され、精査され、テストされた実装に置き換えています。明らかなライブラリ(Androidサポートライブラリ、Androidデザインサポートライブラリ、Gson)については話していません。私はあなたが知らないかもしれないツールについて言及しています。使用したとしても、おそらくまだ使用していません。
標準開発者とマスター開発者の主な違いの1つは、サードパーティライブラリの正しい使用法です。マスター開発者は、初心者の3倍の速さで、通常は短いコードで同じタスクを実行します。これの大部分は、使用するサードパーティライブラリと、それらをプロジェクトに正しく埋め込む方法を知っていることから得られます。私は何年にもわたってAndroidチームの開発、指導、指導を行っており、数十の外部ツールやライブラリを研究して使用してきました。 (私は彼らの実装コードを読んで開発者と彼らの内部について話し合うことさえ知られています。)多くは私が仕事を成し遂げるのを助けるのに非常に効果的でした、しかし真実はほとんどがそうではありませんでした。
そのため、このガイドをまとめました。私の経験と他のモバイル開発者の経験に基づいて、最高のライブラリを使用していることを確認してください。私は7つ選びました。彼らもすぐにあなたのお気に入りのいくつかになると思います。
ライブラリを選択するとき、私は4つの重要な機能を探します。
最初の3つの機能はディールブレーカーです。それらが存在しない場合は、先に進むか、ハンドコーディングを開始します。
以下で取り上げるライブラリは、4つのテストすべてに合格しています。また、モバイル開発の最も困難な側面のいくつかを解決します。
これは、Android用の究極の依存性注入ライブラリです。シンプル、堅牢、超高速(反射なし!)、そして排除することができます たくさん アプリのボイラープレートコードの
そもそもButterKnifeがAndroidのJavaマッピングへのレイアウトであるはずだったと主張する人もいます。
findViewById()
への呼び出しを介して各ビューを直接バインドする必要はなくなりました。代わりに、コードに直接アクセスできる注釈付きのビューがあります。 バターナイフ また、onClick
、onTouch
などの定型的なUIイベントが不要になり、自動挿入されたコードに置き換えられます。
しかし、十分なチットチャット、コードを見てみましょう。
フィールドバインディングを表示します。
class MyButterKnifeActivity extends Activity { @BindView(R.id.name) TextView name; @BindView(R.id.address) TextView address; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_activity); ButterKnife.bind(this); // MUST BE CALLED BEFORE ACCESSING UI FIELDS name.setText(“etc etc”); } }
リソースバインディング:
class ExampleActivity extends Activity { @BindString(R.string.username) String username; @BindDrawable(R.drawable.graphic) Drawable graphic; @BindColor(R.color.bg_color) int bgColor; @BindDimen(R.dimen.lower_padding) Float lowerPadding; // and no need for getResources().getString()/getDrawable/getColor() }
UIイベントバインディング:
@OnClick(R.id.my_button) public void clickHandler(View view) { // onClick logic goes here }
依存性注入に関しては、ButterKnifeに次ぐ2番目です。 AndroidAnnotations わずかに異なるアプローチを使用します。自動生成されたクラスは、一度コツをつかめば、非常に単純です。さらに便利なのは、「名前ベース」の依存性注入が可能になることです。たとえば、@ViewById ListView myUserList;
このフィールドにlayoutListView
を割り当てるようにライブラリーに指示します。同じ名前で。
AndroidAnnotationsも非常に高速ですが、ButterKnifeとは多少異なる方法でそれを実現します。ランタイムバインディングの依存性注入の代わりに、AndroidAnnotationsは、影響を受けるすべてのアクティビティのビルド時の複製を作成し、その接続ロジックをそれらにプッシュします。これにより、手動でコーディングされたロジックと同じパフォーマンスを得ることができます。
しかし、AndroidAnnotationsのインジェクション機能はそれ以上のものです。状態とレイアウトの両方をアクティビティに挿入できます。
AndroidAnnotationsの実装:
@NoTitle @Fullscreen @EActivity(R.layout.my_layout) public class MyActivity extends Activity { @ViewById ListView customerList; // auto-binded to R.id.customerList @App MyApplication app; // auto-binded to app object @AminationRes Animation fadeoutAnimation; @UiThread void updateUI() { // main thread action } }
最後のアノテーションにはもう少し説明が必要です。マルチスレッドAndroidアプリの一般的なタスクは、バックグラウンド(またはワーカー)スレッドからフォワード(またはメインまたはUI)スレッドに切り替えることです。これは、UIコンポーネントへのアクセスを許可する唯一のスレッドです。 。このタスクは複雑ではありませんが、多くの場合必要であり、面倒なコーディングが必要です。
new Handler(Looper.getMainLooper()).post(new Runnable() { logic goes here } ); // NO ANNOTATIONS
AndroidAnnotationsでは、関数に@UiThreadアノテーションを付けるだけで、常に実行されることが保証されます。
@UiThread void updateUI() {..} // WITH ANNOTATIONS
このアノテーションは、標準のAndroidコンポーネントクラス(アクティビティ、サービスなど)に適用されることに注意してください。しかし、自分のクラスにも注釈を付けたい場合はどうなりますか?
ここで、AndroidAnnotationsは、EBean
という新しい概念を考え出します。 @EBean
を使用してクラスをそのようにマークするだけで、準備は完了です。
@EBean public class MyNonComponentClass { @SystemService NotificationManager notifManager; @Bean MyOtherClass dependency; @UiThread void updateUI() { // main thread work goes here } }
EventBus ライブラリは、Android開発者が長年悩まされてきた問題を公園の散歩に変えます。コンポーネント間の通信がこれまでになく簡単になりました。単純なpub / subモデルを使用して、システムの任意の2つの部分間で通信します。
バックグラウンドポーリングサービスは、変更イベントをフィードするためにフラグメントを認識する必要がなくなりました。
EventBusの使用法は簡単です。
に。 イベントクラスを作成します。ここでPOJOを操作するのが最適です。
class NewUserEvent { String fullname; String address; String role; // add getters and setters }
b。 クラス(これらのイベントをサブスクライブするクラス)にイベント処理メソッドを作成します。
class MySubscriber { @Subscribe public void newUserHandler(NewUserEvent event) { // handle NewUserEvent } @Subscribe public void newUserHandler(AnotherEvent event) { // handle AnotherEvent } }
しかし、ちょっと、経験の浅いAndroid開発者は、この時点で立ち止まって質問します。これらのハンドラーのスレッドモデルは何ですか?また、たとえばUIコンポーネントへのアクセスが含まれる場合、ハンドラーをメインスレッドから強制的に実行できますか? 良い質問…
デフォルトでは、すべてのハンドラーメソッドは、EventBus自体によって割り当てられ維持されるスレッドプールから取得されたワーカースレッドで実行されます。メインスレッドで実行するハンドラーメソッドが必要な場合は、サブスクリプションアノテーションを次のように展開します。
@Subscribe(threadMode = ThreadMode.MAIN) public void runOnMainThreadHandler(AnotherEvent event) { … }
警告: この機能を使いすぎないでください!長時間実行される操作は メインスレッドでは実行されません 、そして迅速な操作でも、注意してください。メインスレッドを圧倒することは、アプリを遅く、ジャンプさせ、基本的にユーザーにとって面白くないものにする最も確実な方法です。
c。 サブスクライバークラスのEventBus登録ライフサイクルを管理します。つまり、いつ接続し、いつバスから切断しますか?アクティビティの合理的な登録フローは次のとおりです。
class MySubscriberActivity extends Activity { @Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); // START RECEIVING EVENTS HERE } @Override public void onStop() { EventBus.getDefault().unregister(this); // NO MORE EVENTS super.onStop(); } }
もちろん、上記はほんの一例です。選択した場所で(登録解除)登録を実行できます。
d。 そして最後に、実際にイベントを発生させます。
EventBus.getDefault().post(new MyEvent(“I’m here”));
EventBusの使用について知っておくべきことは他にもたくさんあります。イベントのマルチキャスト(デフォルトの動作)、スティッキーイベントの使用、配信スレッド、優先度などです。しかし、このシンプルでありながら強力なテクノロジーを使い始めるには、上記で十分です。
これは、AndroidのHttpClientを作成する方法です。とてもシンプルでとてもスマートです。ザ・ OkHttpライブラリ 再試行ループ、ペイロードの自動圧縮、Http / 2サポート、接続プーリング、および応答キャッシュを内部で処理するため、不要なネットワークアクセスを回避できます。
OkHttpの使用法は簡単です。
Http POST:
OkHttpClient client = new OkHttpClient(); MediaType JSON = MediaType.parse('application/json; charset=utf-8'); RequestBody body = RequestBody.create(JSON, json_str); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); return response.body().string();
Http GET:
OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(urls[0]) .build(); Response responses = client.newCall(request).execute(); String jsonData = responses.body().string();
OkHttpは、非同期ネットワーク、リクエストリダイレクトルートクエリ、ローカルキャッシュクエリなどの便利な機能もサポートしています。必要に応じて自由に使用してください。ほとんどの開発者は、AndroidのデフォルトのHTTPクライアントであるHttpURLConnectionのよりスマートな代替としてOkHttpを使用しています。実際、このプロジェクト全体は、HttpURLConnectionのプライベートフォークとして開始されました。
その堅牢性が気に入っています。すぐにネットワーク層に追加されます。
ほんの数行のコードで、OkHttpは、ネットワーク層のデバッグと最適化に夜を費やしたようにアプリを動作させます。ピカソ これは、画像のダウンロード、キャッシュ、サイズ変更、およびトリミングを管理するための最も簡単で堅牢な方法です。
この文:
Picasso.with(context).load(url).resize(50,50).centerCrop().into(imageView)
あなたのためにこれを行います:
上記の一連のタスクを構築するには、マスター開発者であっても、何時間もの作業が必要になります。そして、それはあなたがすべてを覚えていることを前提としています。たとえば、サイズ変更の部分を忘れた場合はどうなりますか?
ええと、平均的なAndroidデバイスでは、アプリは50〜60メガバイトのRAMしか取得できず、ほとんどのAndroidデバイスのピクセル対バイト係数は4です。これは、SDカードから13メガピクセルの画像を読み込もうとすることを意味します。 52メガバイトのRAMが必要になります。つまり、アプリはすぐにクラッシュします。
これはピカソの強みの一例に過ぎません。メディアを多用するレガシープロジェクトを最適化/デバッグするときに最初に行うことの1つは、すべての画像の読み込みをピカソに切り替えることです。この1つの簡単な手順がアプリの品質に与える影響に驚かれることでしょう。
このライブラリの力を示す最も強力な証拠の1つ: 過去2年間のGoogle独自のAndroidコードサンプルの多くは、画像の読み込みにピカソを採用しています。
オブジェクトリレーショナルマッピングの略であるORMは、J2EEの時代に普及しました。これにより、POJOを個別のフィールドに変換しなくても、データベースに格納したり、データベースから取得したりできます。
役に立ちましたか? SQLステートメントをコーディングせずにアプリの大部分を記述できるため、非常に重要です。
また、非常に効率的です。昔、ORMプラットフォームはリフレクションに大きく依存しており、遅いことで有名でした。を含む最新のプラットフォーム ActiveAndroid は、はるかに高速であり、ほとんどの実用的な要件では、生のSQLコーディングよりもパフォーマンスのオーバーヘッドに悩まされることはありません。
手作業でコーディングされたSQLステートメント、パフォーマンスのオーバーヘッドはありません。使用法:
に。 カスタムApplicationクラスを拡張して、アプリケーションオブジェクトで初期化します。
public class MyApplication extends extends com.activeandroid.app.Application { … }
b。 データベースに格納する予定の各レコードのクラスを使用して、モデルクラス用に派生したPOJOを作成します。このような各POJOは、独自のテーブルに常駐できます。注釈を使用して、格納されている各メンバーのDBフィールドの名前を指定する必要があります。
@Table(name = 'Categories') public class UserDetails extends Model { @Column(name = 'Name') public String name; @Column(name = 'Address') public String address; @Column(name = 'Age') public int age; }
メンバーのインデックスを設定する場合は、次の注釈を使用します。
@Column(name = 'ID', index = true) public String userID;
c。 ライブラリが最もクラスの高い起動時間(デフォルトの動作)で繰り返されないようにするには、次のマニフェストセクションですべてのモデルクラスを指定することを強くお勧めします。
UserDetails usr = new UserDetails(); usr.save(); // RUNS ON A BACKGROUND THREAD
注意: このリストに表示されていないモデルクラスは、ActiveAndroidによって認識されません。
d。 データベースへの書き込み:
ActiveAndroid.beginTransaction(); try { for (UserDetails u: userList) item.save(); ActiveAndroid.setTransactionSuccessful(); } finally { ActiveAndroid.endTransaction(); }
複数の書き込みが必要な場合、より効率的な方法は、単一のトランザクションでそれらをバッチ処理することです。
new Select() .from(UserDetails.class) .where('name = ?', usr.getName()) .orderBy('Age') .executeSingle();
です。 データベースからPOJOを読み取ります。
protected void onCreate(Bundle savedInstanceState) { mSession = SessionBuilder.getInstance() .setCallback(this) .setSurfaceView(mSurfaceView) .setPreviewOrientation(90) .setContext(getApplicationContext()) .setAudioEncoder(SessionBuilder.AUDIO_NONE) .setAudioQuality(new AudioQuality(16000, 32000)) .setVideoEncoder(SessionBuilder.VIDEO_H264) .setVideoQuality(new VideoQuality(320,240,20,500000)) .build(); mSurfaceView.getHolder().addCallback(this); }
ORMは、サーバー側の開発者としての私の時代にはなくてはならないツールでした。 Androidドメインへの参入がやや遅れました。しかし、ついに、ここにあります:それが得るのと同じくらい簡単なデータベースプログラミング。楽しめ。
リアルタイムビデオストリーミングは、文書化されていないAPI、SDK間のバージョンの違い、リフレクションの使用法などのために、以前は大きな問題でした。
幸いなことに、 libStreaming ストリーミングの複雑さのほとんどをカプセル化し、基本的なストリーミングアプリを数時間で作成できるシンプルで使いやすいAPIを公開することで、これらすべてを変更しました。
一言で言えば、それはビデオストリーミングを合理化します。H.264およびAACで使用するには、次の手順を実行する必要があります。
に。 メインアクティビティのonCreateメソッドでセッションオブジェクトを初期化します。セッションオブジェクトは、ピアへのメディアストリーミングを表します。
mSession.setDestination(destination_server_url); mSession.start();
b。 実際にセッションを開始します。
mSession.stop();
c。 完了したらセッションを停止します。
onCreate()
さて、誤解しないでください。リアルタイムストリーミングは本質的に厄介であり、libStreamingはこの複雑さを取り除きません。しかし、それはほとんどの場合あなたからそれを隠す本当に良い仕事をします。場合によっては、ピアシグナリングポリシーの選択、カメラエンコーディングの選択(通常はMediaCodec / surface-to-bufferを使用する)、パケット化の処理など、複雑さに対処する必要があります。
それでも、libStreamingの背後にいる善良な人々は、これらの複雑さを使いやすいAPIにスムーズにマージすることにさらに努力したことがわかります。
LibStreamingは、H.264、H.263、AAC、AMRなど、Androidアプリで使用されるほとんどのエンコーダーをサポートしています。
このライブラリで素晴らしい結果を得ることができました。最も人気のあるストリーミングアプリのいくつかは、インフラストラクチャの一部としてそれを使用しています。このニーズに遭遇した場合は、メディアストリーミングエクスペリエンスがはるかにスムーズになると確信しています。
このライブラリの背後にある動機から始めましょう: メモリリーク 。 Androidアプリは、特にコーディングに注意しないと、それらの傾向があります。実際、メモリリークの作成は非常に簡単です。あなたがする必要があるのは、そのコンテキストの外にアクティビティ参照を保存することです。実際、アクティビティのコンテキスト外に単一のビューオブジェクトへの参照を格納する場合でも、リークが発生します。
どうして?ビュー(実際にはすべてのビュー)は、それを含むアクティビティへのコンテキスト参照を内部に格納するためです。ビューへの参照が保持されている限り、ビュー内のアクティビティ(ドローアブル、ビュー階層、リソースなど)を含むアクティビティは、ガベージコレクタによって再利用できません。
リークしているアクティビティへの参照を保持することは、静的パラメータとして常に明白であるとは限りません。内部クラスを作成するか、アクティビティ内にスレッドを生成するたびに、そのアクティビティへの参照が作成され、その内部クラスまたはスレッドが完了するまでアクティビティが再利用されない場合があります。
リークはもちろんAndroidに固有のものではありませんが、メモリリソースが限られているモバイルシステムであるため、影響はより直接的です。リソースを大量に消費する単一のアクティビティへの参照を漏らすだけで、アプリが「 メモリ不足 」例外。
どうすればそれらから保護できますか?皮切りに 厳密なコーディング慣行 、 もちろん。しかし、私たち全員が経験豊富なAndroid開発者であるわけではなく、経験豊富な開発者でさえルールを忘れることがあります。
メモリリークに重点を置いた定期的なコードレビューは役立つ場合がありますが、時間がかかります。また、一部のリークは本当に卑劣で、単なるコードレビューでは検出が困難です。
DDMSのメモリツールを使用することは、アプリがリークしているかどうかを時間をかけて知るための優れた方法です。あなたは間違いなくそれを使うべきです。 ただし、リークの原因はわかりません。
の登場 リークカナリア 救助へ。これは、世の中で最高のメモリリーク検出器であり、 自動 — 1行または2行のコードのように—すべてのアクティビティのリーク検出。
これを使用するには、leakCanaryをアプリのオブジェクトで初期化するだけです public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); // more initialisations } }
:
ActivityRefWatcher
これで完了です。 LeakCanaryはメモリリークを監視し、リークを検出すると通知を送信します。
LeakCanaryは、onDestroy()
というオブジェクトを自動注入することでこの魔法を実現します。すべてのアクティビティにアクセスし、 refWatcher = LeakCanary.install(this);
後の参照カウントを監視しますと呼ばれています。破壊されたアクティビティの参照カウントが0より大きい場合は、リークを意味するだけです。
重要: リーク検出は、デバッグモードのアプリケーションでのみ機能します。リリースモードAPKでリークをテストしないでください(LeakCanaryではテストしないでください)。
しかし、システムの他の部分のリークをテストしたい場合はどうすればよいですか?ここで、LeakCanaryはrefWatcherと呼ばれるオブジェクトを提供します。これは、実際には初期化呼び出しの戻り値です。
refWatcher.watch(my_soon_to_be_reclaimed_obj);
間もなく回収される値を監視するために使用できます。もっと正確に言えば、私が思う価値観はすぐに取り戻されるでしょう。これを行うには、次の電話番号に電話してください。
|_+_|
ライブラリは、このオブジェクトがウォッチコールの直後にリリースされていないかどうかを通知します。
この「短時間」の価値はどこにも見つかりませんでしたが、おそらくそれほど重要ではありません。 LeakCanaryを使用すると、問題なく機能します。貴重です。
経験豊富な開発者は、これらのライブラリを使用してコーディングとデバッグのフェーズを数日から数週間短縮するため、同じことができない理由はありません。
要約すると、Androidライブラリの私の選択があなたのために何ができるかはここにあります:
バターナイフ –自動挿入されたコードは、アプリの定型コードの多くを排除するのに役立ちます。これは、Android向けの究極のコードインジェクションです。もっと言う必要がありますか?
AndroidAnnotations –非常に高速な自動生成クラスと名前ベースのコードインジェクションを使用して、手動でコーディングされたロジックよりもパフォーマンスを低下させることなく時間を節約します。
EventBus –コンポーネントを分離してコードをより堅牢にし、コンポーネント間の通信がこれまでになく簡単になりました。
emacsとnotepad ++
OkHttp – HttpURLConnectionの巧妙な代替品で、非同期ネットワーク、要求リダイレクトルートクエリ、ローカルキャッシュクエリなどをサポートします。
ピカソ –合理化された画像操作は、現在Googleで使用されているほど優れています。これは、メディアの多いプロジェクトや特定のレガシープロジェクトで大幅な時間の節約になります。
ActiveAndroid – ORMは、パフォーマンスのオーバーヘッドなしで簡単になりました。
LibStreaming –主要なストリーミングアプリで使用されるリアルタイムビデオストリーミング。
これらはあなたの時間の価値がある唯一のAndroidライブラリですか?確かにそうではありません。しかし、私はあなたにこれを約束します:あなたの次のプロジェクトでそれらのいずれかを使用することはあなたをはるかに優れた開発者にするでしょう。それらの動作を確認したい場合は、私の GitHub 。
すでにそれらの一部またはすべてを使用している場合、または代替ライブラリを使用している場合は、以下のコメントで経験を共有することをお勧めします。
関連: 開発者向けAndroid7.0:新機能、パフォーマンスアップグレード、その他気にしないもの