Trayendo lo mejor de vuelta al nativo
Incluso mientras experimentamos con React Native, también continuamos acelerando nuestros esfuerzos en Nativo. Hoy tenemos la app de Platzi en nativo y algunos proyectos en proceso. Algunos de estos proyectos se inspiraron en las mejores partes y aprendizajes de nuestra experiencia con React Native.
Para comenzar queremos dar a entender el por qué optamos por un desarrollo Nativo y no probar con otras tecnologías como Flutter (Ya varias personas no lo han comentado).
Como hablamos anteriormente queríamos mejorar el rendimiento y la experiencia de los estudiantes en la aplicación móvil, siempre supimos que un desarrollo nativo nos iba a dar ese beneficio, podríamos crear una aplicación móvil capaz de tener todas las características y funcionalidades que se requiere para tener a nuestros estudiantes felices.
Ahora bien ¿Por qué no Flutter? Como hablamos en el anterior blog React Native - App Nativa en Platzi la inmadurez de estas tecnologías es notable, puede que funcionen bien en casos específicos y sencillos, como solo crear vistas, componentes, y cosas relacionadas a UI, pero para aplicaciones las cuales requiere un uso muy específico de cada característica en Android o iOS se quedan atrás, por ejemplo, notificaciones, reproducción background, descargas y player.
Con esto en mente nosotros empezamos a armar la arquitectura en Android, la cual nos iba a ayudar en el desarrollo y en los procesos para poder tener la aplicación móvil de Platzi lo antes posible.
Primero escogimos Kotlin como lenguaje de programación oficial para el desarrollo de aplicaciones móviles en Android. Este lenguaje con sus super poderes nos ayudó mucho a la hora de la implementación; la adaptación y la curva de aprendizaje fue muy sencilla. Si quieres aprender más de este asombroso lenguaje de programación, tenemos el Curso de Kotlin para Android.
Luego optamos por usar la arquitectura más popular para el desarrollo en Android, la cual es MVVM con Clean Architecture. Esto nos ayuda tener un proyecto sostenible y escalable, con código desacoplado, fácil de testear y con la creación nuevas funcionalidades rápidamente. Además la estructura del proyecto es muy sencilla de navegar.
Aparte de esto, agregamos varios patrones de diseño tales como:
A continuación, mostramos un ejemplo de cómo fue la implementación entre capaz usando MVVM como arquitectura y los patrones de diseño. Lo haremos con la pantalla de perfil, la cual necesita mostrar el progreso de los cursos que has tomado en Platzi.
Primero tenemos un ProfileProgressFragment
el cual es la vista, esta hace el llamado al ViewModel para traer los datos que se necesitan mostrar, este llamado se hace en la función getCoursesProgress
y nos suscribimos al LiveData para obtener los datos con la función observeCoursesProgressResponse
.
classProfileProgressFragment : Fragment() {
privateval profileViewModel: ProfileViewModel by viewModel() // DI with KoinoverridefunonViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
getCoursesProgress()
}
privatefungetCoursesProgress() {
profileViewModel.getCoursesProgress()
profileViewModel.observeCoursesProgressResponse()
.observe(viewLifecycleOwner, Observer {
handleStateRequest(it)
})
}
}
Este ProfileViewModel
recibe en el constructor el repositorio el cual nos hace la petición al server o a la base de datos local, declaramos e inicializamos una variable getCoursesProgressProfile
que es nuestro LiveData que estará notificando a la vista los cambios que hayan en esta misma.
classProfileViewModel(
privateval profileRepository: ProfileRepository // DI with Koin
) : ViewModel() {
privatevar getCoursesProgressProfile: MutableLiveData<Result<Any>> = MutableLiveData()
funobserveCoursesProgressProfile(): LiveData<Result<Any>> {return getCoursesProgressProfile
}
fungetCoursesProgressProfile() {
getCoursesProgressProfile.postValue(Result.Loading)
viewModelScope.launch {
val response = profileRepository.getCoursesProgress()
getCoursesProgressProfile.postValue(response)
}
}
}
Finalmente el repositorio ProfileRepository
es el que decide si hacer la petición al server remoteDataSource
o a la base de datos local localDataSource
, acá usamos Coroutines para hacer estás peticiones de forma asincrónica y así mismo no afecte al hilo principal o el hilo de la vista.
classProfileRepository(
privateval remoteDataSource: DataSource, // DI with Koinprivateval localDataSource: DataSource // DI with Koin
) {
suspend fungetCoursesProgress(): Result<String> {returntry {
withContext(ioDisPatcher) { // Coroutinesval progressCache = localDataSource.getDataSource()
if (progressCache is Result.Success) {
Result.Success(progressCache.data.toString())
}
val response = remoteDataSource.getDataSource(0, "enpoint")
if (response is Result.Success)
Result.Success(data)
} else {
Result.Error(response.toString())
}
}
} catch (e: Exception) {
Result.Error(e.toString())
}
}
}
De esta manera el Repositorio retorna lo solicitado, el ViewModel notifica a la vista y esta muestra los datos al usuario.
Y finalmente gracias a Android Jetpack usamos algunos Architecture Components que nos ayudan a crear aplicaciones de una manera más sencilla, los cuales son:
Es emocionante estar en una empresa que no tiene miedo de probar nuevas tecnologías pero que se esfuerza por mantener una barra increíblemente alta para la calidad, la velocidad y la experiencia del desarrollador. Al final del día, React Native fue una herramienta esencial en las funciones de envío y nos dio nuevas formas de pensar sobre el desarrollo móvil.
Todo esto nos llenó de retos, pero finalmente podemos mostrar algo por lo que valio la pena, tanto en Android como en iOS, pudimos mejorar muchas cosas y dar a nuestros estudiantes un producto que realmente vale la pena usar.
Ahora tenemos una aplicación móvil nativa. La cual irá mejorando aún más, poco a poco para darte la mejor experiencia. En Platzi uno de nuestros pilares es Our community comes first y es algo que queremos reflejar con todo lo nuevo que está por venir.
Si esto suena como un viaje y quieres saber más. Cuéntanos en los comentarios.
Ahora puedes descargar la nueva app de Platzi 100% nativa 👉Platzi - Cursos Online
I am a Happy Platzi student. I trust you team.
Lo único que espero de la App de Platzi es que llegue a la Huawei AppGallery
Entonces… ¿habéis hecho la app nativa también para iOS?
Te agradecería que se pueda ver platzi live por la app
Yo sé que sí se puede, es cuestión de abrir la app mientras se está transmistiendo.
Lo feo es que la app no sincroniza muy bien el progeso de los cursos y toca buscar las clases manualmente. No guarda el progreso
Hola Esteban! Muy interesante este tema de arquitectura. Un par de preguntas y sugerencias que creo que ayudarían a mejorar si me lo permties 🙌, por que habeís decidido no tener un Usecase o Interactor como una capa despues del ViewModel? El ViewModel al ser parte de la capa de presentación no debería gestionar solamente los LiveData y actualizar un livedata correspondiente dependiendo del estado de la llamada digamos Success/Error y dejar la gestión de las llamadas al use case?
Kotlin suele postar mucho por la inmutabilidad porque usais un liveData var en lugar de dos liveDatas de la siguiente forma:
private val _getCoursesProgressProfile: <MutableLiveData> = MutableLiveData<TuObjeto>() val CoursesProgressProfile : LiveData<TuObjeto> = _getCoursesProgressProfile
Esto ayudaría a eliminar la función que devuelve el LiveData ya que puedes obtener la información desde el Fragment con un observer.
Porque habeís decidido usar .postValue en lugar de .value e el LiveData?
En el repository veo que usan el withContext(Dispatchers.IO){
} creo que no es necesarío al estar ya dentro de la coroutine padre del viewModelScope.launch almenos que quieras obtener una información para luego depender de ella y usar ambas te pongo un ejemplo de como lo usamos en donde yo trabajo:
Y luego a ese user le aplicamos logica de negocio y podemos seguir con la suspend function.
Espero tu respueta y recordarte que son solo cosas que he visto como colega desarrollador Android que quisiera comentar 😉, no tienen nada de mala vibra. Gracias por cambiar a Nativo 😄. A nunca parar de aprender💪
Quise decir “Kotlin suele apostar” pero no me deja cambiar ya lo que he escrito 😅.
Deberian tener la opcion de descargar clases tambien en web, no solo en movil
Hola Esteban, una pregunta para IOS que arquitectura trabajan la app?
Yo agradezco mucho el mirroring al Chromecast… ese feature para mi es un must!
Pues la verdad la app sí ha mejorado mucho, antes era dificil mover la barra de estado para adelantar o atrasar el curso, a veces cogía la función, a veces no. Y ahora puedes seguir reproduciendo en background, como si fuera un podcast. Para algunos cursos que no necesitan que eses viendo al profe esto es genial
Excelente reflexión de aprender de estas tecnologías un poco inmaduras para la funcionalidad y perfomance que platzi requiere.
¿Entonces la recomendación si quiero aprender a hacer aplicaciones móviles, es darme duro con Kotlin?
Me gustan mucho sus variables tan semánticas.
Cuándo podremos ver los live’s en pantallas inteligentes o chrome. El jueves pasado todavía no me dejaba.
Felicidades por la nueva implementación de modelo y arquitectura.
Bonito día.
Amo la app y a Platzi ❤️
A mí no me va la app en mi celular, inicia sesión, pero no me reproduce nada ningún curso aún sea de audio 😦, ni las miniaturas de los cursos se ven 😔
Dime que versión tienes, para ver que puede ser.
Mira los permisos de la aplicación, a mi me fallaba porque no le había dado permiso al storage, chequea en las Settings de la app desde los Settings de tu teléfono.
Que buena noticia Ojala tengan en cuenta los dispositivos Android con pantallas de 10’5 pulgadas tanto portrait como landscape
Actualmente la App después de la ultima actualización tiene demasiados bugs sobre todo con la conexión de google Chromecast
Habrá forma de instalar la aplicación en una Android TV?
No entendí casi nada de la explicación técnica y por eso entré a Platzi 😃
Cada día me motiva más a aprender todo del mundo de la programación.
Esta genial el post. Gracias por compartir esta info.
Good