後に:エルpokedexエヌアンドロイドyきれいな建築


ねえ、Ma chamacos!イェー・デ・デ・リグス・デ・デット・ド・ヌドロス・コンM .エエスタOcasiは、n nキレロConarles sobreウンpoquito mは、デdesarrolloアンドロイドです.コモUstedes Sabrは、Nは、UNOデロスEjercicios que como ingenierosデソフトウェアnosotros hacemos - para pulir nuestras tソフトウェアcicas en el desarrolloデソフトウェアes el desarrolloデルポピュラーpokedex、エルcual es la gu de de todo maestro pok es mon mon pr cicamente su mano derecha.

<研究ノート> Rays es Le POKEDEX


コモ・ヤ・ロー・メッシオンの作品『エヌ・ラ・グー』について

<武井>


プエス・ビエン,デモン・デ・エスト・デラローロ・エ・ケルシュリン100 % , se Estuvieron Applzando Pr . ccicas usadas hoy en d ' le a en el desarrollo m . vle la como la実装について
<翻訳>パラオ,ユモトス・コウンパラドール・ラ・インサイチィー・デ・デ・ディノエンシアスとフイスマ・アルマンド・ラ・パルト・デ・データ・エヌM .エヌラParteデLlamadasは、API API Tambiを使用します.
LuegoパラEl Backend、SE実装pokeapi comoバックエンド、mismoque que ha haのConfertiteエヌdel desarrolloエヌproe eceecto en diferentes lenguajes、sobre todo enn los que ususos en frontend(js,dart,typescript)y Apps m del viles(swift,kotlin,java)
IninasとしてのFinalmente paraラスLibrer und , Ese Thepo Theo comoに関する非現実的なものに対する利用可能性
  • 滑空
  • レトロフィット
  • GSON(EXTESI DEN N DEレトロフィット)
  • ソープクリーン建築


    クリーン建築ESは、マルコデTrabajo Propuesto PorロバートC .マーティンcomo formaデ構造家ニュエストロC通dioエヌcapas、mismas que solamente se pueden comunicarにラス・エストええとラスラディオスを集中させます.
    クリーン建築のEl Eququema

    yラスcapas、tomando en cuentaアンドロイド息子ラスsiguientes:
  • UI:La InterfazデUsuario(エル断片).ペルーいいえQueereデカールque vayasメートルトダラl lgadas datos enエルフラグメント(mala praxis)、パラエロseアメリカエルビューモデルデルミッモ、que es donde viene la siguiente capa.
  • Presentaciは、以下を言います:息子clase que se comunican con lae cle eインターフェースは、interacciとn nuestra aplicaciを得ます.コモLo Mencionは、enエルプント前に、Aqueをはいています.
  • ユースケースを使用して:Estas Clase se Encargan de Negocio de Timinente Parel el Mannelo de Negocio Pertinente Parel El Manejo de Nodos de Nutratra Aplicaci
  • Regitorios O実体:AQA - es donde se albergan todas las llamadas datos internos y externos de nuestra aplicaci

    カコPR


    Ahora Bien , Culo un Coco Pr , Culo un Caso Pr . Culo un Caso Pr . Culo un Caso Pr . Culo un Caso Pr .
  • Reactivex(タルヴェズ私aviavite algo sobre corrutinas).
  • inyecci disde endependencias.
  • エルModelo MVVMは、利用可能なApplzadoエヌm m Villesです.
  • Esta formaのレトロフィットとしてのNuestro Lamadoについて
    Capa 4 :リポジトリ
    interface RestApi {
        @GET("region")
        fun getRegions(): Observable<RegionResult>
    
        @GET("region/{region}")
        fun getDetailedRegion(@Path("region") region: String): Observable<RegionDetailedResult>
    
        @GET("pokedex/{pokedex}")
        fun getPokedex(@Path("pokedex") pokedex: String): Observable<PokedexResult>
    
        @GET("pokemon/{pokemon}")
        fun getPokemonByName(@Path("pokemon") pokemon: String): Observable<PokemonResult>
    
        @GET("pokemon-species/{pokemon}")
        fun getPokemonSpeciesByName(@Path("pokemon") pokemon: String): Observable<PokemonSpeciesResult>
    }
    
    カダUnoデロスmは、Dos HaがそうであるTheDos Deshados en Dicha Interfaz Serであります.Posteriororte , se Reiziza la Manufaciti in Dicha Interfaz por medio de una clase :
    class RestApiImp {
        companion object{
            var retrofit: Retrofit? = null
            val REQUEST_TIMEOUT: Long = 30
            var okHttpClient: OkHttpClient? = null
    
            fun getClient(): Retrofit {
                if(okHttpClient == null)
                    initOkHttpClient()
    
                if(retrofit == null) {
                    retrofit = Retrofit.Builder()
                        .baseUrl(Constant.MAIN_URL)
                        .client(okHttpClient!!)
                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build()
                }
    
                return retrofit!!
            }
    
            private fun initOkHttpClient() {
                var httpClient: OkHttpClient.Builder = OkHttpClient().newBuilder()
                    .connectTimeout(REQUEST_TIMEOUT, TimeUnit.SECONDS)
                    .readTimeout(REQUEST_TIMEOUT, TimeUnit.SECONDS)
                    .writeTimeout(REQUEST_TIMEOUT, TimeUnit.SECONDS)
    
                var interceptor: HttpLoggingInterceptor = HttpLoggingInterceptor()
                interceptor.level = HttpLoggingInterceptor.Level.BODY
                httpClient.addInterceptor(interceptor)
    
                httpClient.addInterceptor { chain ->
                    var original = chain.request()
    
                    val newRequest = chain.request().newBuilder()
                        .addHeader("Accept", "application/json")
                        .build()
    
                    chain.proceed(newRequest)
                }
    
                okHttpClient = httpClient.build()
            }
        }
    }
    
    コモpueden ver , la clase cuenta con un "コンパニオンオブジェクト",エルcual es el s des mil en kotlin de宣言ar na cle est en tica een dicho objeto , tenemos el m ee todo getclient , mismo que se encargar und de realizar la implementation to i n n de retrofitLa Extensiは、パラggson y国連迎撃器パラinyectar cabeceras antesデllamar al要請(es aquoのdonde podrはエーモスのinyectarトークン、sin禁輸のno necesitamos en esta ocasiのn)を要求します.
    Luego、Pasamosは、ロサンゼルスリポジトリのパースです.Las M ' s To Pas Obtener Los Diferentes Tipos de "Pokedex "をめぐって
    interface PokedexRepository {
        fun getPokedex(pokedex: String): Observable<PokedexResult>
    }
    
    <研究ノート>人間の倫理観
    class PokedexRepositoryImp: PokedexRepository {
        private var apiRequest: RestApi = RestApiImp.getClient().create(RestApi::class.java)
    
        override fun getPokedex(pokedex: String): Observable<PokedexResult> {
            return apiRequest.getPokedex(pokedex)
        }
    }
    
    en esta interfaz y clase , podemos nosotros ver que que invocaremos como talレトロなhacia un endpoint de los definados en restapiKT pero como parte de laきれいな建築、キーンse encargarは、デ・エロSerとロスInteractorの上で言います.
    キャパ3:俳優
    <研究ノート>ロス・リポジトリとしてのミサ・マーラ・レーク
    interface PokedexInteractor {
        fun getPokedex(pokedex: String): Observable<PokedexResult>
    }
    
    Y La Clase que実装者:
    class PokedexInteractorImp(private val pokedexRepositoryImp: PokedexRepositoryImp,
            private val pokemonRepositoryImp: PokemonRepositoryImp): PokedexInteractor {
        val logger: Logger = LoggerFactory.getLogger(PokedexInteractorImp::class.java.simpleName)
    
        override fun getPokedex(pokedex: String): Observable<PokedexResult> {
            return pokedexRepositoryImp.getPokedex(pokedex)
                .doOnNext { response ->
                    run {
                        for(item: Pokemon in response.pokemonEntries) {
                            var pokemonID: String = item.pokemonSpecies.url
                                .replace(Constant.MAIN_URL, "")
                                .replace("pokemon-species", "")
                                .replace("/", "")
    
                            item.pokemonImage = Constant.POKEMON_IMAGE_URL + pokemonID + ".png"
                            pokemonRepositoryImp.getPokemon(item.pokemonSpecies.name)
                                .subscribeOn(Schedulers.io())
                                .subscribe({response2 -> item.pokemonDetails = response2}, {t -> logger.error(t.message)})
                        }
                    }
                }
                .doOnComplete { logger.debug("Service complete") }
                .onErrorReturn { error ->
                    logger.error(error.message)
                    null
                }
        }
    }
    
    y como podemos天文台en pokedexinteractorimpKT , Ecarcarde de Armar L . Gias Complejas en Genas Freejas de Nogcio de la AplicaciEPAにおけるEPAの役割について
    チャパ2:presentaci
    <研究ノート>アンドロイドにおける表現と表現の仕方: Nuestro Fragmento en Cuesti - en N . Por Lo Tanto , Dicho Viewmodels Tiene que Estar Bestlecido y Asignado dentro del FragmentoアルマノエルViewmodel como sigue :
    class PokedexInfoViewModel : ViewModel() {
        var compositeDisposable = CompositeDisposable()
        lateinit var dependencies: ApiDependencies // I'll talk about this later
        var pokemon: MutableLiveData<MutableList<Pokemon>> = MutableLiveData()
    
        fun getPokedex(pokedex: String) {
            compositeDisposable.add(dependencies.getPokedex(pokedex)
                .subscribeOn(Schedulers.io())
                .subscribe(
                    {res -> pokemon.postValue(res.pokemonEntries) },
                    {t: Throwable -> Log.e(ContentValues.TAG, t.message!!) }
                )
            )
        }
    }
    
    コンEsto、nosotros vamos armando la capa 2 y dejamos todo dispuesto que la capa 1 no nnicamente quede a la escucha de la informaci n n que llegue al momento de request ery y seguir el flujo de ida y velta conforme a la clean architecture
    CACA 1 : UI
    Finalmente , El Carcarado de invocar Todo este Caminito ser Ele Fragment ( Peues usar活動, Pero gastar - en s s s memory )
    class PokedexInfoFragment : Fragment() {
    
        private lateinit var viewModel: PokedexInfoViewModel
        private lateinit var toolbar: Toolbar
        private val dependencies: ApiDependencies by inject()
        lateinit var items: MutableList<Pokemon>
        lateinit var recyclerView: RecyclerView
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setHasOptionsMenu(true)
        }
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
    
            val view = inflater.inflate(R.layout.pokedex_info_fragment, container, false)
    
            val activity = requireActivity() as AppCompatActivity
            toolbar = view.findViewById(R.id.tb_pokedex_info)
            activity.setSupportActionBar(toolbar)
    
            activity.supportActionBar!!.title = arguments?.getString("pokedex")!!
                .capitalize(Locale.getDefault()).replace("-", " ") + "'s Pokedex"
            activity.supportActionBar!!.setDisplayHomeAsUpEnabled(true)
    
            return view
        }
    
        override fun onOptionsItemSelected(item: MenuItem): Boolean {
            when (item.itemId) {
                android.R.id.home -> {
                    var bundle = bundleOf("region" to arguments?.getString("region"))
                    Navigation.findNavController(requireView()).navigate(R.id.action_pokedexInfoFragment_to_regionFragment, bundle)
                    return true
                }
            }
    
            return super.onOptionsItemSelected(item)
        }
    
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            super.onActivityCreated(savedInstanceState)
            viewModel = ViewModelProvider(this).get(PokedexInfoViewModel::class.java)
    
            viewModel.dependencies = dependencies
            viewModel.pokemon.observe(viewLifecycleOwner, Observer {
                items = it
                initRecyclerView()
            })
            viewModel.getPokedex(arguments?.getString("pokedex")!!)
        }
    
        private fun initRecyclerView() {
            val listener = View.OnClickListener() {
                val bundle = bundleOf("pokemon" to it
                    .findViewById<TextView>(R.id.txt_pokemon_name)
                    .text.toString().toLowerCase(Locale.getDefault()),
                    "pokedex" to arguments?.getString("pokedex"))
    
                Navigation.findNavController(requireView())
                    .navigate(R.id.action_pokedexInfoFragment_to_pokemonFragment, bundle)
            }
    
            recyclerView = requireView().findViewById(R.id.rv_pokedex_info)
            recyclerView.setHasFixedSize(true)
            recyclerView.layoutManager = GridLayoutManager(requireContext(), 3)
            recyclerView.adapter = PokedexInfoAdapter(items, listener)
        }
    
        override fun onDetach() {
            viewModel.compositeDisposable.dispose()
            items.clear()
            super.onDetach()
        }
    
        override fun onDestroy() {
            viewModel.compositeDisposable.dispose()
            items.clear()
            super.onDestroy()
        }
    }
    
    Varios Mは、1つの息子息子のParte de la apiデアンドロイド、罪禁輸息子デ不可欠な輸入品(ondetach y ondestroy)パラqueエルエルModModel no se Queen en Memania al MomentoデCambiarデ断片、SalirデLaアプリo Alg Ant n n Punto enエルque Cel Lico de vidaデラapp se vea terminado o interrumpidoをオーバーライドします.
    <研究ノート>トド・オン・アクティ-ト-
            viewModel.pokemon.observe(viewLifecycleOwner, Observer {
                items = it
                initRecyclerView()
            })
            viewModel.getPokedex(arguments?.getString("pokedex")!!)
    
    アル・モメント・デ・アネラル・エル・ビューモデルの研究(第1部)

    シグイティエンパロス


    Hasta ahorita Ando Viendo el Trabajar Lo Siguiente ya que que tiene una versi des estable
  • mejorarエルUX/UIデラアプリ.Ahorita Lo hiceは、y yシーコです.
  • Agregar国連ニュースフィードenエルダッシュボード.あいにきの愛について
  • en lugar de usar rxkotlin,poder cambiar a corrutinas para la parte as la ncrona y tener una partiva de trabajar las lllamadas de este tipo .AunqueラVerdad、大豆Mは、ファンデReactivex queラスcorrutinas、Pero宇野Nunca Sabe Cuによって、NDO Necesitarを得ますTrabajarコンEllas.
  • リバイサルque no hayaメモリリークエヌラアプリ.
  • ci/cd
  • comes es costumbreは、彼de comentar queなし大豆のmemeor desarrolladorデアンドロイドy queタルvez este cのdioの海のエルmejor que hayas visto y me gustar - me mejorarlo.SI Te Interesa dejar Tsの問題、ダーレスター、forkearlo o ayudarme a mejorar、puedes hacerlo en el sigigienteリポジトリ:https://github.com/RZEROSTERN/roadtocertification_pokedex
    Igualmente、SI quieren dejarのSus ComentItalia、Pueden Hacerlo Bajoエステポスト.フェリスデContestarlos.
    ブエノpues、エスパーque lesハヤgustadoエステ柱、Aunque Largo、栄養塩エヌCuestiones queタルvez puedan sacarデdudas a m ' s s de una persona.
    ハッピーコーディング!