Micro Optimizaciones Implementadas - gorozcoua/team18 GitHub Wiki
Explicación:
Luego de la inspección ejecutada por el Lint de Android, se procede a eliminar recursos no utilizados reportados por la herramienta.
Explicación:
Se inspeccionan manualmente las clases para identificar imports en color gris que corresponden a los no utilizados.
Explicación:
Se refactoriza la clase adaptadora NetWorkServiceAdapter para evitar la creación de objetos innecesarios dentro de los ciclos for.
Explicación: El Lint de Android sugiere eliminar el estilo de borde de los botones superiores de navegación.
Explicación: Esta microoptimización implementa un sistema de caché local que almacena los datos de las pistas de los álbumes. Esto reduce significativamente las llamadas a la red, mejora el rendimiento de la aplicación y permite un funcionamiento básico sin conexión. El sistema verifica primero si los datos están en caché antes de realizar una llamada a la red.
// AlbumDetailRepository.kt
suspend fun refreshTracksData(albumId: Int): List<Track> {
val cache = CacheManager.getInstance(application.applicationContext)
val potentialResp = cache.getTracks(albumId)
return if (potentialResp.isEmpty()) {
val tracks = NetworkServiceAdapter.getInstance(application)
.getTracksForAlbum(albumId)
cache.addTracks(albumId, tracks)
tracks
} else {
potentialResp
}
}
Explicación: Esta microoptimización implementa un sistema robusto de manejo de estados utilizando LiveData. Permite una gestión eficiente de los errores de red y las actualizaciones de la UI. El sistema mantiene un estado consistente de la aplicación y evita problemas comunes como la pérdida de estado durante cambios de configuración.
// AlbumDetailViewModel.kt
private val _eventNetworkError = MutableLiveData(false)
val eventNetworkError: LiveData<Boolean>
get() = _eventNetworkError
private fun refreshDataFromRepository() {
try {
viewModelScope.launch(Dispatchers.Default) {
withContext(Dispatchers.IO) {
val data = albumDetailRepository.refreshData(albumId)
_tracks.postValue(data)
}
_eventNetworkError.postValue(false)
_isNetworkErrorShown.postValue(false)
}
} catch (e: Exception) {
_eventNetworkError.value = true
}
}
Explicación: Esta microoptimización se centra en la eficiencia de la interfaz de usuario. Implementa una configuración optimizada del RecyclerView y un sistema de observación de datos que reduce las recreaciones innecesarias de vistas. Esto resulta en una UI más fluida y un mejor rendimiento general.
// AlbumDetailFragment.kt
tracksRecyclerView.apply {
layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
adapter = trackAdapter
}
viewModel.tracks.observe(viewLifecycleOwner) { tracks ->
trackAdapter.updateTracks(tracks)
}
Explicación: Esta microoptimización define una estructura de datos clara y eficiente para los álbumes. El modelo está diseñado para facilitar el almacenamiento en caché y la serialización/deserialización de datos. Incluye un identificador único para cada álbum, lo que permite una gestión eficiente de la caché.
// Album.kt
data class Album (
val albumId:Int,
val name:String,
val cover:String,
val releaseDate:String,
val description:String,
val genre:String,
val recordLabel:String
)
Explicación: Esta microoptimización implementa corrutinas en los ViewModels para manejar operaciones asíncronas de manera eficiente. Utiliza el scope del ViewModel para garantizar la cancelación automática cuando el ViewModel se destruye, mejorando el manejo de recursos y la experiencia del usuario.
// AlbumViewModel.kt
private fun refreshDataFromNetwork() {
viewModelScope.launch(Dispatchers.IO) {
try {
val data = albumRepository.refreshData()
_albums.postValue(data)
_eventNetworkError.postValue(false)
} catch (e: Exception) {
_eventNetworkError.postValue(true)
}
}
}
Explicación: Esta microoptimización implementa un sistema de caché en los repositories que reduce las llamadas a la red. Primero verifica si los datos están disponibles localmente antes de realizar una petición a la red, optimizando el consumo de datos y mejorando los tiempos de respuesta.
// AlbumRepository.kt
suspend fun refreshData(): List<Album> {
val cache = CacheManager.getInstance(application.applicationContext)
val potentialResp = cache.getAlbums()
return if (potentialResp.isEmpty()) {
val albums = NetworkServiceAdapter.getInstance(application)
.getAlbums()
cache.addAlbums(albums)
albums
} else {
potentialResp
}
}
Explicación: Esta microoptimización convierte las llamadas asíncronas basadas en callbacks a corrutinas, permitiendo un código más limpio y fácil de mantener. Utiliza suspendCoroutine para transformar las operaciones asíncronas tradicionales en corrutinas.
// NetworkServiceAdapter.kt
suspend fun getAlbums() = suspendCoroutine<List<Album>>{ cont->
requestQueue.add(getRequest("albums",
{ response ->
val resp = JSONArray(response)
val list = mutableListOf<Album>()
for (i in 0 until resp.length()) {
val item = resp.getJSONObject(i)
list.add(Album(albumId = item.getInt("id"),
name = item.getString("name"),
cover = item.getString("cover"),
recordLabel = item.getString("recordLabel"),
releaseDate = item.getString("releaseDate"),
genre = item.getString("genre"),
description = item.getString("description")))
}
cont.resume(list)
},
{
cont.resumeWithException(it)
}))
}
Explicación: Esta microoptimización implementa el uso de múltiples dispatchers para diferentes tipos de operaciones, permitiendo una mejor gestión de recursos y un rendimiento optimizado según el tipo de operación.
// AlbumDetailViewModel.kt
private fun refreshDataFromRepository() {
try {
viewModelScope.launch(Dispatchers.Default) {
withContext(Dispatchers.IO) {
val data = albumDetailRepository.refreshData(albumId)
_tracks.postValue(data)
}
_eventNetworkError.postValue(false)
}
} catch (e: Exception) {
_eventNetworkError.value = true
}
}
Explicación: Esta microoptimización implementa un sistema robusto de manejo de errores en las corrutinas, permitiendo una mejor gestión de excepciones y proporcionando feedback adecuado al usuario.
// MusicianViewModel.kt
private fun refreshDataFromNetwork() {
viewModelScope.launch(Dispatchers.IO) {
try {
val data = musicianRepository.refreshData()
_musicians.postValue(data)
_eventNetworkError.postValue(false)
_isNetworkErrorShown.postValue(false)
} catch (e: Exception) {
Log.e("NetworkError", "Error getting musicians", e)
_eventNetworkError.postValue(true)
}
}
}
Explicación: Esta microoptimización define las dependencias necesarias para implementar corrutinas en Android, asegurando la compatibilidad y el rendimiento óptimo de las operaciones asíncronas.
// build.gradle
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
}
Estas microoptimizaciones trabajan en conjunto para proporcionar una base sólida para operaciones asíncronas en la aplicación, mejorando significativamente el rendimiento y la experiencia del usuario.
## 10. Gestión de Recursos
**Explicación**:
Esta microoptimización se centra en la gestión eficiente de recursos de la aplicación. Implementa un inflado optimizado de vistas y un mejor manejo de la memoria. Esto reduce el consumo de recursos y previene problemas comunes como fugas de memoria.
```kotlin
// AlbumDetailFragment.kt
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_album_detail, container, false)
return view
}
Explicación: Esta microoptimización se centra en la primera estrategia para manejar caché de imágenes proporcionada por Glide. La estrategia consiste tanto en la utilización en sí de la librería Glide como de la estrategia de manejar caché en disco para un pintado más óptimo de imágenes en la interfaz.
// AlbumAdapter.kt
Glide.with(holder.itemView.context)
.load(album.cover)
.apply(RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.ALL))
.into(holder.albumImage)