Tanpa perkenalan panjang, saya akan memberi tahu Anda cara mengatur arsitektur aplikasi Anda dengan cepat dan mudah. Materi ini akan berguna bagi mereka yang tidak terbiasa dengan pola mvvm dan coroutine Kotlin.
Jadi, kami memiliki tugas sederhana: untuk menerima dan memproses permintaan jaringan, untuk menampilkan hasilnya dalam tampilan.
Tindakan kami: dari aktivitas (fragmen), kami memanggil metode yang diinginkan ViewModel -> ViewModel mengakses pegangan retrofit, mengeksekusi permintaan melalui coroutine -> respons dikirim ke data langsung sebagai peristiwa -> dalam aktivitas yang menerima peristiwa kami mentransfer data ke tampilan.
Penyiapan proyek
Ketergantungan
Terwujud
<manifest ...> <uses-permission android:name="android.permission.INTERNET" /> </manifest>
Pengaturan Retrofit
Buat objek
NetworkService Kotlinovsky. Ini akan menjadi klien jaringan kami - singleton
Singleton UPD digunakan untuk kemudahan pemahaman. Komentar menunjukkan bahwa lebih tepat untuk menggunakan inversi kontrol, tetapi ini adalah topik yang terpisah.
object NetworkService { private const val BASE_URL = " http://www.mocky.io/v2/"
Antarmuka api
Kami menggunakan permintaan yang dikunci ke layanan palsu.
Jeda kesenangan, di sini dimulai keajaiban corutin.
Kami menandai fungsi kami dengan kata kunci yang
menyenangkan ...Retrofit belajar untuk bekerja dengan fungsi menangguhkan Kotlin dari versi 2.6.0, sekarang secara langsung menjalankan permintaan jaringan dan mengembalikan objek dengan data:
interface Api { @GET("5dcc12d554000064009c20fc") suspend fun getUsers( @Query("page") page: Int ): ResponseWrapper<Users> @GET("5dcc147154000059009c2104") suspend fun getUsersError( @Query("page") page: Int ): ResponseWrapper<Users> }
ResponseWrapper adalah kelas pembungkus sederhana untuk permintaan jaringan kami:
class ResponseWrapper<T> : Serializable { @SerializedName("response") val data: T? = null @SerializedName("error") val error: Error? = null }
Tanggal kelas
Pengguna data class Users( @SerializedName("count") var count: Int?, @SerializedName("items") var items: List<Item?>? ) { data class Item( @SerializedName("first_name") var firstName: String?, @SerializedName("last_name") var lastName: String? ) }
ViewModel
Kami membuat kelas
BaseViewModel abstrak dari mana semua ViewModel kami akan diwarisi. Di sini kita tinggal lebih detail:
abstract class BaseViewModel : ViewModel() { var api: Api = NetworkService.retrofitService()
Acara
Solusi keren dari Google adalah membungkus kelas tanggal dalam kelas pembungkus Peristiwa di mana kami dapat memiliki beberapa negara, biasanya LOADING, SUCCESS, dan ERROR.
data class Event<out T>(val status: Status, val data: T?, val error: Error?) { companion object { fun <T> loading(): Event<T> { return Event(Status.LOADING, null, null) } fun <T> success(data: T?): Event<T> { return Event(Status.SUCCESS, data, null) } fun <T> error(error: Error?): Event<T> { return Event(Status.ERROR, null, error) } } } enum class Status { SUCCESS, ERROR, LOADING }
Begini cara kerjanya. Selama permintaan jaringan, kami membuat acara dengan status LOADING. Kami sedang menunggu respons dari server dan kemudian membungkus data dengan acara tersebut dan mengirimkannya dengan status yang ditentukan lebih lanjut. Dalam tampilan kami memeriksa jenis acara dan, tergantung pada negara, mengatur negara yang berbeda untuk tampilan. Pola arsitektur MVI didasarkan pada filosofi yang sama.
ActivityViewModel
class ActivityViewModel : BaseViewModel() {
Dan akhirnya
Mainaktivitas
class MainActivity : AppCompatActivity() { private lateinit var activityViewModel: ActivityViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) activityViewModel = ViewModelProviders.of(this).get(ActivityViewModel::class.java) observeGetPosts() buttonOneClickListener() buttonTwoClickListener() }
Kode sumber