Sin largas presentaciones, le diré cómo organizar rápida y fácilmente una arquitectura conveniente de su aplicación. El material será útil para aquellos que no están muy familiarizados con el patrón mvvm y las rutinas de Kotlin.
Por lo tanto, tenemos una tarea simple: recibir y procesar una solicitud de red, mostrar el resultado en una vista.
Nuestras acciones: desde la actividad (fragmento), llamamos al método deseado ViewModel -> ViewModel accede al controlador de modificación, ejecutando la solicitud a través de las rutinas -> la respuesta se envía a los datos en vivo como un evento -> en la actividad que recibe el evento transferimos los datos a la vista.
Configuración del proyecto
Dependencias
Manifiesto
<manifest ...> <uses-permission android:name="android.permission.INTERNET" /> </manifest>
Configuración de actualización
Cree un objeto Kotlinovsky
NetworkService . Este será nuestro cliente de red - singleton
UPD singleton se utiliza para facilitar la comprensión. Los comentarios indicaron que es más apropiado usar la inversión de control, pero este es un tema separado.
object NetworkService { private const val BASE_URL = " http://www.mocky.io/v2/"
Interfaz api
Utilizamos solicitudes bloqueadas para el servicio falso.
Pausa la diversión, aquí comienza la magia de la corutina.
Marcamos nuestras funciones con la palabra clave
suspender diversión ...La actualización aprendió a trabajar con las funciones de suspensión de Kotlin de la versión 2.6.0, ahora ejecuta directamente una solicitud de red y devuelve un objeto con datos:
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 es una clase de contenedor simple para nuestras solicitudes de red:
class ResponseWrapper<T> : Serializable { @SerializedName("response") val data: T? = null @SerializedName("error") val error: Error? = null }
Fecha clase
Usuarios 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
Creamos una clase abstracta
BaseViewModel de la que se heredará todo nuestro ViewModel. Aquí nos detenemos con más detalle:
abstract class BaseViewModel : ViewModel() { var api: Api = NetworkService.retrofitService()
Eventos
Una solución genial de Google es envolver las clases de fechas en una clase de envoltura de eventos, en la que podemos tener varios estados, generalmente CARGANDO, ÉXITO y 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 }
Así es como funciona. Durante una solicitud de red, creamos un evento con el estado CARGANDO. Estamos esperando una respuesta del servidor y luego envolvemos los datos con el evento y los enviamos con el estado especificado más adelante. En la vista, verificamos el tipo de evento y, según el estado, establecemos diferentes estados para la vista. El patrón de arquitectura MVI se basa en la misma filosofía.
ActivityViewModel
class ActivityViewModel : BaseViewModel() {
Y finalmente
Mainactividad
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() }
Código fuente