リストは次のように見えます。
興味があれば、猫をお願いします。
私たちは
当然、すべてはアプリケーションのアーキテクチャによって決まります。 私の経験に基づいて、ほとんどの場合、次のアプリケーション構造が必要です。
ご覧のとおり、アプリケーションは3つの層に分割されています。「顔」、データストレージ、および非同期コマンドのサービスで、ほとんどの場合、ロジックは非表示になっています。
私はホリバーを育てて建築について議論したくはありません。私はそれをどのように、そして同僚がそれをどのように行うかを説明するだけです。
なぜそうなのか
コンテンツプロバイダーは、データ変更通知を備えた非常に強力な機能であり、すぐに使用できます。 主にベースのラッパーとして使用します。 そこでインターネットからデータを適切にロードする方法を見つけられませんでした。
非同期コマンドのサービス -名前から明らかなことはすべて、非同期で(別のスレッドで)アクションを実行します。 ほとんどすべてのアクションは非同期である必要があります-データベースへの書き込み、インターネットへのアクセス、およびカウント。
なぜ「非同期コマンド」なのですか? ここでも、すべてがシンプルです-各アクションは完全なチームです。 どのパラメータで開始するか、それらをどうするか、および完了の通知を知っています。
ここで、 evilduckはすでにすべてを詳細に説明しています。
「マズル」 -データを表示するためのアクティビティ/フラグメントのセット。 リポジトリからのデータの読み込み全体が非同期である必要があることに注意してください(1つの番号であっても、UIからデータベースへのアクセスはありません)。 そして、ここでローダーマネージャーが私たちの助けになります-すぐに使える機能です。 CursorLoaderの方を見る価値がある
自転車
おそらくすべてのプログラマーが自分の自転車を作ったでしょう。 それらからも恩恵があります-あなたはあなたが必要なものとその理由のすべての落とし穴を理解し始めます。 しかし、毎回自転車を書くのは良くありません。 また、別のプロジェクトからロールすることはできません。 コードは販売されており、顧客の所有物です。
もちろん、あなたのコードは、私たちがlibを使用することを書いた顧客との契約で、libで発行、公開できます。 しかし、あらゆる場合にlibを書くことはそれほど簡単ではありません。さらに、すでに別の自転車を持っているのに、なぜ別の自転車を作るのか、そしてバグはすでに発見され修正されています。 結局、それは私に起こりました。
私は敵が反射的であるというわけではありませんが、コードを生成する人を好みます。 デビューするのが便利で、そこで何が起こっているかをいつでも確認できます。
何よりも、注釈が好きです。 ライブラリの私のコレクション全体は、この原則と実質的に一致しています。 始めましょう...
グラディ
このライブラリはコマンドサービスを実装しています。
- チームはケンセリットになれます
- AsyncTask愛好家は移行に気付かないでしょう
- コールバックのサポートがあり、それらは非常に使いやすいです。
私は、コマンドを実行するための静的メソッドを作成し、コールバックを典型化することを好みます。
コールバックは任意のオブジェクトにできますが、入力することを好みます。 これは、コンパイラが私たちを助けるのに役立ちます。
そして、それはカルベックを公共の活動方法に掛ける誘惑からあなたを守り、それによってOOPの柱の一つ-カプセル化に違反します:)
まさにその理由から、静的な起動方法が必要です。
public class LoginCommand extends GroundyTask{ private static final String ARG_PASSWORD = "arg_password"; private static final String ARG_USER = "arg_username"; @Override protected TaskResult doInBackground() { String userName = getStringArg(ARG_USER); String password = getStringArg(ARG_PASSWORD); //do something return succeeded(); } public static void start(Context context, BaseLoginCommandCallback callback, String login, String password) { Groundy.create(LoginCommand.class) .arg(ARG_USER, login) .arg(ARG_PASSWORD, password) .callback(callback) .queueUsing(context); } public static abstract class BaseLoginCommandCallback{ @OnSuccess(LoginCommand.class) public void handleSuccess(){ onLoginSuccess(); } @OnFailure(LoginCommand.class) public void handleFailure(){ onLoginError(); } protected abstract void onLoginSuccess(); protected abstract void onLoginError(); } }
後付け
RESTサービスを呼び出すための非常に単純なツール。よく書かれたものとあまり書かれていないものの両方。 コードは実際には生成されませんが、非常に簡単です。
私はSpring Androidの方向を見ましたが、それはどういうわけか重いです。
public interface ServicesFootballua { String API_URL = "http://services.football.ua/api"; @GET("/News/GetArchive") NewsArchive getNewsArchive(@Query("pageId") long pageId, @Query("count") long count, @Query("datePublish") String date); }
まあ、それは私たちがそれを使用する方法です
private static ServicesFootballua API = new RestAdapter.Builder() .setServer(ServicesFootballua.API_URL) .build() .create(ServicesFootballua.class); ................................... archive = API.getNewsArchive(PAGE_ID, COUNT, dateFormat.format(getTodayTime()));
コンバーター、httpクライアント、その他の多くのものを置き換えることができます。
AnnotatedSQL
注釈用のデータベースとコンテンツプロバイダーを生成します。
私のクラフト、私は完全に満足しています。 いくつかの記事がここにあります 。
最近、キックで、 evilduckが Maven Centralで公開されました
ORMLiteを見ましたが、Androidには適していないようです。 通常、すべてをすべて引き出す必要はありません。 通常のsqlとvishkiはほとんどすべてを解決します。
Androidアノテーション
私は非常に長い間このライブラリを見て、最近プロダクションでそれをzayuzatすることに決めました-ヌードクラスを使用する必要があるという事実にもかかわらず、私はそれが好きでした。
最も強力なツールであり、主なことは、 Backgroundをうまく使用したり、頭をオンにしたりしないことです。
良いプラス-あなたはそれをほとんど痛みなく切ることができます。
私はAQueryとDaggerを見ましたが、IMHO Android Annotationsにはすでにすべてがあります。
唯一のマイナスは、「コンパイルしない理由」というエラーを探すのが難しい場合があります。
オフサイトですべての機能について読むことができます。 追加したいのは、常に静的メソッドを作成してアクティブ化を開始し、フラグメントを作成することだけです。 これにより、すべてのコードが1か所に分離され、コード内の誰も組み込みクラスであるか元のクラスであるかを知りません。
たとえば、 AlertDialogFragmentフラグメントにはメソッドがあります
public static void show(FragmentActivity activity, DialogType type, int titleId, String msg, int positiveTitleId, OnDialogClickListener positiveListener) { DialogUtil.show(activity, DIALOG_NAME, AlertDialogFragment_.builder() .titleId(titleId) .errorMsg(msg) .positiveButtonTitleId(positiveTitleId) .dialogType(type).build() ).setOnClickListener(positiveListener); }
そして、コードのどこでも呼び出しは次のようになります
AlertDialogFragment.show(BaseActivity.this, DialogType.CONFIRM, R.string.some_title, getString(R.string.some_message), R.string.btn_edit, new OnDialogClickListener() {...............}
AlertDialogFragment_の存在を誰も知らない
Android DBコモン
つい最近、この素晴らしいライブラリが見つかりました。 なぜなら どこでも、どこでもローダーを使用します。通常、結果はカーソルです。 CursorAdapterをいつでもzozyuzatして、必要なものを表示できます。
しかし、これはリストを使用するように私たちに提供しますが、カーソルの上に、そしてリストとともに、みんなのお気に入りのArrayAdapter。
ここにそのような共生があります-Listを見てArrayAdapterを使用しますが、実際はカーソルとアダプターカーソルです。 本当の「ストリートマジック」:)
彼らはあまりにも怠け者ではなく、内部に小さなキャッシュを備えたLazyListを作成しました。
カーソルの代わりにリストを取得するには、カーソル文字列をオブジェクトに変換する関数( transform )を記述する必要があり、カーソルではなくリストを返すローダーを取得します
return CursorLoaderBuilder.forUri(URI_ITEMS) .projection(ItemConverter.PROJECTION) .where(ItemTable.ACTIVE_STATUS + " = ?", 1) .where(ItemTable.DESCRIPTION + " like ?", "%" + searchText + "%") .transform(new ItemConverter()).build(getActivity());
しかし、私たちが知っているように、カーソルを何らかのオブジェクトに読み込む必要がある場合があります。たとえば、何かをカウントする必要があります。
public Loader<Integer> onCreateLoader(int i, Bundle bundle) { return CursorLoaderBuilder .forUri(ITEMS_URI) .projection("count(" + ItemTable.GUID + ")") .where(ItemTable.ACTIVE_STATUS + " = ?", 1) .where(ItemTable.STOCK_TRACKING + " = ?", 1) .where(ItemTable.TMP_AVAILABLE_QTY + " <= " + ItemTable.RECOMMENDED_QTY) .wrap(new Function<Cursor, Integer>() { @Override public Integer apply(Cursor c) { if (c.moveToFirst()) { return c.getInt(0); } return 0; } }).build(DashboardActivity.this); }
これはとても簡単な方法です。
これは非常に簡単な例です。 可能性ははるかに低いです。
同時に、wrapメソッドはまだ別のスレッドで実行されます。 そのため、データベースにアクセスしてさらにデータを取得できます。
私が言ったように、これは時々必要です。
終了
UI自体には多数の異なるライブラリ(主にコンポーネント)が使用されることは明らかですが、これは既にデザイナーの想像力に依存しています:)
さて、これはaptが作成するGradleのビルドスクリプトです( はい、既に特別なプラグインがありますが、まだ試していません )。
そうそう-android-db-commons-0.1.6.jarをlibsフォルダーにダウンロードする
ext.androidAnnotationsVersion = '2.7.1'; configurations { apt } dependencies { compile fileTree(dir: 'libs', include: '*.jar') compile 'com.google.guava:guava:13.0.1' compile 'com.telly:groundy:1.3' apt 'com.telly:groundy-compiler:1.3' apt "com.googlecode.androidannotations:androidannotations:${androidAnnotationsVersion}" compile "com.googlecode.androidannotations:androidannotations-api:${androidAnnotationsVersion}" compile 'com.github.hamsterksu:android-annotatedsql-api:1.7.8' apt 'com.github.hamsterksu:android-annotatedsql-processor:1.7.8' } android.applicationVariants.all { variant -> aptOutput = file("${project.buildDir}/source/apt_generated/${variant.dirName}") variant.javaCompile.doFirst { aptOutput.mkdirs() variant.javaCompile.options.compilerArgs += [ '-processorpath', configurations.apt.getAsPath(), '-processor', 'com.annotatedsql.processor.provider.ProviderProcessor,com.annotatedsql.processor.sql.SQLProcessor,com.googlecode.androidannotations.AndroidAnnotationProcessor,com.telly.groundy.GroundyCodeGen', '-AandroidManifestFile=' + variant.processResources.manifestFile, '-s', aptOutput ] } }
ご清聴ありがとうございました。