JetPackコンポーネントベースのMVVMフレームワークを簡単に構築


Brick
github gitee
紹介する
Android開発者がJetPackコンポーネントに基づいてMVVMフレームワークを構築する注釈処理フレームワークの構築を支援する.注記によって自動的にViewModelのFactoryクラス、lazyメソッドなどを生成します.プロジェクトの任意の場所にROMを注入するdaoレイヤインタフェースとRetrofitライブラリ内のapiインタフェースをサポートします.
特長android は、brickを軽量レベルの注入フレームワークとして理解することができ、使用は非常に簡単であり、4〜6個の注釈を用いて動作することができる.brickは主にコンパイル期間中に動作し、Appの実行時に追加のパフォーマンス消費を生じず、ボリュームの増大の問題を心配することなく、1つの注釈ライブラリだけがandroidプロジェクトにパッケージされます.
適用範囲
  • は、androidxライブラリではなくsupportライブラリを使用します.
  • は、JetPackViewModel組立体を使用する.
  • は、Retrofitをネットワーク要求ライブラリとして使用する.
  • は、ROOMデータベース・フレームワークを使用します.(オプション)
  • サービス側は、マルチポート、マルチIPの項目である.(オプション)
  • 導入
  • androidエンジニアリングのルートディレクトリのbuild.gradleファイルの適切な場所に次のコードを追加します:
  • buildscript {
        ...
        ext {
            brick_version = '0.2.0'
        }
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
        dependencies {
            classpath "com.gitee.numeron.brick:plugin:$brick_version"
        }
    }
    
    allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }
    
  • あなたのandroidエンジニアリングでbrickのandroidモジュールを有効にするbuild.gradleファイルの適切な場所に次のコードを追加します:
  • ...
    apply plugin: 'kotlin-kapt'
    apply plugin: 'brick'
    ...
    dependencies {
        ...
        implementation "com.gitee.numeron.brick:annotation:$brick_version"
        kapt "com.gitee.numeron.brick:compiler:$brick_version"
    }
    

    使用
    一、@Provide注記の使用方法:
  • あなたが作成したViewModelサブクラスに@Provide注記
  • を追加
    @Provide
    class WxAuthorViewModel: ViewModel() {
        ...
    }
    
  • brick注釈プロセッサを動作させるには3つの方法があります:
  • Terminal端末にgradlew :[ModuleName]:kaptDebugKotlin実行スクリプトを入力する.
  • Android Studioの右側のGradle拡張バーで[PrjectName] -> [ModuneName] -> Tasks -> other -> kaptDebugKotlinを順に見つけ、実行スクリプトをダブルクリックします.
  • Ctrl + F9プロジェクト全体をコンパイルします.以上の3つの方法のいずれかを選択してbrick注釈プロセッサを実行します.
  • スクリプトの実行が終了すると、
  • という2つのパケット・レベル・メソッドが生成されます.
  • lazyWxAuthorViewModel()拡張メソッドは、ActivityまたはFragmentで直接呼び出せばよい.
  • get()メソッドは、lazyメソッドの使用が不便な場合に、このメソッドを使用してViewModelのインスタンスを取得できます.注:lazyWxAuthorViewModel方法はget()方法の包装です.生成メソッドを直接使用すると、対応するViewModelインスタンスを作成できます:
  • private val wxAuthorViewModel by lazyWxAuthorViewModel()
    

    またはonCreate()の後にgetで作成します.
    private lateinit var wxAuthorViewModel: WxAuthorViewModel
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        wxAuthorViewModel = get(this)
    }
    

    二、@Inject注記の使い方
    -2.必要に応じて、Retrofitのインスタンスを取得する方法に@RetrofitInstanceを追加する.
    @RetrofitInstance
    val retrofit: Retrofit by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
        Retrofit.Builder()
            .client(okHttpClient)
            .baseUrl(WANDROID_BASE_URL)
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
    }
    
    val okHttpClient: OkHttpClient by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
        val logInterceptor = HttpLoggingInterceptor()
        logInterceptor.level = HttpLoggingInterceptor.Level.BODY
        OkHttpClient.Builder()
            .addInterceptor(logInterceptor)
            .callTimeout(15, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(60, TimeUnit.SECONDS)
            .connectTimeout(15, TimeUnit.SECONDS)
            .build()
    }
    

    注:@RetrofitInstance注記は、publicによって修飾されたval属性またはメソッドにのみマークされます.val属性またはメソッドは、object またはcompanion objectにおいても、パケットレベル属性/メソッドであってもよい.
    -1.オプションとして、RoomDatabaseのインスタンスを取得する属性または方法には、@RoomInstance、例えば、
    @RoomInstance
    val wandroidDatabase: WandroidDatabase by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
        Room.databaseBuilder(CONTEXT, WandroidDatabase::class.java, "wandroid.db")
            .build()
    }
    

    注:@RoomInstance注記は、publicによって修飾されたval属性またはメソッドにのみマークされます.val属性またはメソッドは、object またはcompanion objectにおいても、パケットレベル属性/メソッドであってもよい.
  • は、Retrofit ApiインターフェースおよびWxAuthorRepoクラス
  • があると仮定する.
    interface WxAuthorApi {
        @GET("wxarticle/chapters/json  ")
        suspend fun getWxAuthorList(): List
    }
    
    class WxAuthorRepo {
        ...
    }
    
    
  • WxAuthorRepoにlateinit varで修飾されたWxAuthorApiフィールドを追加し、@Injectでマーク:
  • class WxAuthorRepo {
    
        @Inject
        lateinit var wxAuthorApi: WxAuthorApi
    
    }
    
  • ViewModelでlateinit var修飾WxAuthorRepoフィールドを作成し、@Inject
  • と表記します.
    @Provide
    class WxAuthorViewModel: ViewModel() {
        @Inject
        private lateinit var wxAuthorRepo: WxAuthorRepo
    }
    

    タグ付け後、ビジネスコードの作成を続行すれば、@Injectタグ付けされたすべてのフィールドは、コンパイル中にインスタンスが自動的に取得または作成され、いつ値付けされるか心配する必要はありません.注意:lateinit var修飾フィールドですが、値を付けてはいけません.これは致命的なエラーを引き起こします.注意:@Injectが注入できるタイプは、RetrofitapiインタフェースとROOMdaoインタフェース、およびパラメトリック構造の有無のクラスのみです.
    三、マルチサーバー或いはマルチポートの処理方法:
    アクセスアドレスまたはポートがbaseUrlと異なる別のRetrofit apiインタフェースがあると仮定すると、Retrofitapiインタフェースに@Portおよび@Url注釈を追加してurlまたはportを設定することができる.
  • @Portの使用:
  • @Port(1080)
    interface ArticleApi {
    
        @GET("wxarticle/list/{chapterId}/{page}/json")
        suspend fun getArticleList(@Path("chapterId") chapterId: Int, @Path("page") page: Int): Paged
    }

    この注釈を追加すると、brickはコンパイル中に@RetrofitInstance注釈タグのRetrofitインスタンスと@Portポート番号に基づいて、Retrofitインスタンスを再作成し、新しいRetrofitインスタンスを使用してArticleApiインスタンスを作成します.
  • @Urlの使用:
  • @Url("http://www.wanandroid.com:1080/")
    interface ArticleApi {
        @GET("wxarticle/list/{chapterId}/{page}/json")
        suspend fun getArticleList(@Path("chapterId") chapterId: Int, @Path("page") page: Int): Paged
    }
    @Portの使用とほぼ一致し,実現の原理も同様である.
    付録1
    生成されたWxAuthorViewModels.ktファイル:
    //kotlin     , Activity/Fragment   by  
    fun ViewModelStoreOwner.lazyWxAuthorViewModel(): Lazy =
        LazyWeChatAuthorViewModel(this)
    
    //    , Activity/Fragment onCreate      
    fun get(owner: ViewModelStoreOwner): WxAuthorViewModel {
      val factory = WxAuthorViewModelFactory()
      return ViewModelProvider(owner, factory).get(WxAuthorViewModel::class.java)
    }
    
    private class WxAuthorViewModelFactory : ViewModelProvider.Factory {
      @Suppress("UNCHECKED_CAST")
      override fun  create(clazz: Class): VM = WxAuthorViewModel() as VM
    }
    
    private class LazyWxAuthorViewModel(
      private val owner: ViewModelStoreOwner
    ) : Lazy {
      private var _value: WxAuthorViewModel? = null
    
      override val value: WxAuthorViewModel
        get() {
          if(_value == null) {
            _value = get(owner)
          }
          return _value!!
        }
    
      override fun isInitialized(): Boolean = _value != null
    }
    

    付録2
    逆コンパイル後のWxAuthorViewModel.class:
    class WxAuthorViewModel extends ViewModel {
    	
        private final WxAuthorRepo wxAuthorRepo = new WxAuthorRepo();
    
    }
    

    付録3
    逆コンパイル後のWxAuthorRepo.class:
    class WxAuthorRepo {
    	
        private final WxAuthorApi wxAuthorApi = RuntimeKt.getRetrofit().create(WxAuthorApi.class);
        
        public final WxAuthorApi getWxAuthorApi() {
        	...
        	return wxAuthorApi;
        }
    
    }
    

    付録4WxAuthorApi @Port注記を追加したWxAuthorRepo.class:
    class WxAuthorRepo {
        
        private final WxAuthorApi wxAuthorApi = newRetrofit(RuntimeKt.getRetrofit(), 1080, null).create(WxAuthorApi.class);
        
        public final WxAuthorApi getWxAuthorApi() {
            ...
            return wxAuthorApi;
        }
    
        private final Retrofit newRetrofit(Retrofit retrofit, int port, String url) {
          if (port > 0) {
             HttpUrl httpUrl = retrofit.baseUrl().newBuilder().port(port).build();
             return retrofit.newBuilder().baseUrl(httpUrl).build();
          } else if(url != null && url.length() != 0) {
             return retrofit.newBuilder().baseUrl(url).build();
          }
           return retrofit;
       }
    
    }
    

    まとめclassを逆コンパイルした後のコードと、文章全体を逆コンパイルした後、brickjavaclassにコンパイルした後、classdexにコンパイルする前に、classのバイトコードを修正し、@Injectにマークされたフィールドに値を付け、実現した注入フレームワークであると大まかな結論が得られる.現在、ViewModelへの注入は、生成方法を手動で呼び出して初期化する必要があります.これは、コードをコンパイルする前にASに赤いエラーマークが付いています.次に、@InjectViewModelの作成をサポートさせることが主な仕事です.完了したら、文章を送りましょう.