So I have finished a weather app where it was fully working a month ago. Then yesterday, I ran the app again and I ended up getting a blank screen. This app is using an API, so I checked it and the API is still available and working. Not sure why I’m getting a blank screen.
P.S. I am using Jetpack Compose
Here’s the code that is causing the emptyList
Settings View Model
@HiltViewModel
class SettingsViewModel @Inject constructor(
private val repository: WeatherDbRepository
): ViewModel() {
private val _unitList = MutableStateFlow<List<Unit>>(emptyList())
val unitList = _unitList.asStateFlow()
init {
getUnitList()
}
private fun getUnitList() {
viewModelScope.launch(Dispatchers.IO) {
repository.getUnits().distinctUntilChanged()
.collect{listOfUnits ->
if (listOfUnits.isNullOrEmpty()){
Log.d("TAG", "getUnitList: Empty List")
}else{
_unitList.value = listOfUnits
}
}
}
}
fun insertUnit(unit: Unit) = viewModelScope.launch { repository.insertUnit(unit) }
fun updateUnit(unit: Unit) = viewModelScope.launch { repository.updateUnit(unit) }
fun deleteUnit(unit: Unit) = viewModelScope.launch { repository.deleteUnit(unit) }
fun deleteAllUnits() = viewModelScope.launch { repository.deleteAllUnits() }
}
Repository
class WeatherDbRepository @Inject constructor(private val weatherDao: WeatherDao) {
fun getFavorites(): Flow<List<Favorite>> = weatherDao.getFavorites()
suspend fun insertFavorite(favorite: Favorite) = weatherDao.insertFavorite(favorite)
suspend fun updateFavorite(favorite: Favorite) = weatherDao.updateFavorite(favorite)
suspend fun deleteALlFavorite() = weatherDao.deleteAllFavorites()
suspend fun deleteFavorite(favorite: Favorite) = weatherDao.deleteFavorite(favorite)
suspend fun getFavById(city: String): Favorite = weatherDao.getFavByID(city)
fun getUnits(): Flow<List<Unit>> = weatherDao.getUnits()
suspend fun insertUnit(unit: Unit) = weatherDao.insertUnit(unit)
suspend fun updateUnit(unit: Unit) = weatherDao.updateUnt(unit)
suspend fun deleteAllUnits() = weatherDao.deleteAllUnits()
suspend fun deleteUnit(unit: Unit) = weatherDao.deleteUnit(unit)
}
App Module(DI)
@Module
@InstallIn(SingletonComponent::class)
class AppModule {
@Provides
@Singleton
fun provideWeatherDao(weatherDatabase: WeatherDatabase): WeatherDao =
weatherDatabase.weatherDao()
@Provides
@Singleton
fun provideWeatherDatabase(@ApplicationContext context: Context): WeatherDatabase =
Room.databaseBuilder(
context,
WeatherDatabase::class.java,
"weatherD"
)
.fallbackToDestructiveMigration()
.build()
@Provides
@Singleton
fun provideOpenWeatherApi(): WeatherApi {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(WeatherApi::class.java)
}
}
The Log (getUnitsList log is at the bottom)
08/07 15:03:47: Launching 'app' on Pixel 3 XL API 30.
Install successfully finished in 696 ms.
$ adb shell am start -n "com.example.weatherapp/com.example.weatherapp.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 3468 on device 'Pixel_3_XL_API_30 [emulator-5554]'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/mple.weatherap: Late-enabling -Xcheck:jni
I/mple.weatherap: Unquickening 12 vdex files!
W/mple.weatherap: Unexpected CPU variant for X86 using defaults: x86
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
D/libEGL: loaded /vendor/lib/egl/libEGL_emulation.so
D/libEGL: loaded /vendor/lib/egl/libGLESv1_CM_emulation.so
D/libEGL: loaded /vendor/lib/egl/libGLESv2_emulation.so
W/mple.weatherap: Class androidx.compose.runtime.snapshots.SnapshotStateList failed lock verification and will run slower.
Common causes for lock verification issues are non-optimized dex code
and incorrect proguard optimizations.
D/HostConnection: HostConnection::get() New Host Connection established 0xf2f8fa50, tid 3495
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_sync_buffer_data ANDROID_EMU_read_color_buffer_dma GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_2
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
D/EGL_emulation: eglCreateContext: 0xf2f90d90: maj 2 min 0 rcv 2
D/EGL_emulation: eglMakeCurrent: 0xf2f90d90: ver 2 0 (tinfo 0xf32f1c90) (first time)
I/Gralloc4: mapper 4.x is not supported
D/HostConnection: createUnique: call
D/HostConnection: HostConnection::get() New Host Connection established 0xf2f92d10, tid 3495
D/goldfish-address-space: allocate: Ask for block of size 0x100
D/goldfish-address-space: allocate: ioctl allocate returned offset 0x3efffe000 size 0x2000
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_sync_buffer_data ANDROID_EMU_read_color_buffer_dma GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_2
I/OpenGLRenderer: Davey! duration=727ms; Flags=1, IntendedVsync=1214569752715, Vsync=1214653086045, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=1214662199300, AnimationStart=1214662216300, PerformTraversalsStart=1214662432500, DrawStart=1215266847200, SyncQueued=1215283423600, SyncStart=1215284670600, IssueDrawCommandsStart=1215284716800, SwapBuffers=1215296537700, FrameCompleted=1215298216000, DequeueBufferDuration=186800, QueueBufferDuration=588900, GpuCompleted=72904454231491230,
I/Choreographer: Skipped 34 frames! The application may be doing too much work on its main thread.
W/mple.weatherap: Accessing hidden method Ljava/lang/invoke/MethodHandles$Lookup;-><init>(Ljava/lang/Class;I)V (greylist, reflection, allowed)
D/TAG: getUnitList: Empty List
D/ProfileInstaller: Installing profile for com.example.weatherapp
I’ll leave my GitHub repo link for further observations. Thank You for the help
GitHub Link: https://github.com/OEThe11/WeatherApp/tree/Trials
2
Answers
in my case rebuilding gradle again fixed the problem
also try to clear build
The problem is at the logic you have on the
MainScreen
.You have not considered the fact that on a clean install of an application the Room DB is going to be empty. So you are not allowing the application to do a network request in case it cannot find the selected
unitFromDb
.If you comment that logic it works:
You have to consider adding a default value in the DB if this is the first time the application starts or request from the user to select one if there is nothing selected.
To also answer your question. I suspect that you had done a sucessful request for the weather and you application had the offline data, so coding afterwards the faulty logic you application was working with the offline data, or it had the required value on the DB so it can request for new data from the network. Now that you did a clean install on the application with all the logic you stepped on that faulty case.