1

I'm pretty much a beginner in Kotlin, Room, Flows and viewmodels. The Flow data coming from the viewmodel seems to be working quite well as soon as I launch the app, updating the Jetpack Compose LazyColumn in my MainActivity with data coming from Room Database as I keep inserting or deleting data in the DB through Android Studio's App Inspector and until the device is rotated. After the device is rotated the LazyColumn just stops being receiving new data (but the list still remains populated with what it had up to before device rotation). At this stage, when I add data to the DB, the LazyColum just keeps displaying the old data, until I rotate the device again, triggering recomposition and updating the list with the fresh data.

This is my situation:

OrderDao.kt

@Dao
interface OrderDao {

    //just grabbing what I got from the DB and returning a Flow
    @Query("SELECT * FROM orders")
    fun loadAllOrders(): Flow<List<Order>>

}

OrderRepository.kt

class OrderRepository (context: Context) {

    private val db : OrderDatabase
    val orderDao : OrderDao

    init{
        db = Room.databaseBuilder(
            context.applicationContext,
            OrderDatabase::class.java, "orders"
        ).fallbackToDestructiveMigration().build()

        orderDao = db.orderDao()
    }

    fun getOrders(): Flow<List<Order>> {

        return orderDao.loadAllOrders()
    }

    
}

Also the Database gets initialized in the repository as you can see, which I believe is not a good practice and it's something I need to see to fix, but if there is a good soul that could give me a hint it would be much appreciated. Anyways..

MainActivityViewModel.kt

class MainActivityViewModel(activity : Activity) : ViewModel() {

    private var repository = OrderRepository(activity)

    val mainUiState: StateFlow<MainActivityUiState> = repository.getOrders().map { MainActivityUiState(it) }
        .stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(5_000L),
        initialValue = MainActivityUiState()
    )

    data class MainActivityUiState(val itemList: List<Ordine> = listOf())


}

And my MainActivity.kt which contains the LazyColumn

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val viewModel= MainActivityViewModel(this@MainActivity)
            val orders  by viewModel.mainUiState.collectAsState()


            OrdersTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Column() {
                        OrderList(activity = this@MainActivity, orders = orders)
                        
                    }

                }
            }

        }
    }


}

@Composable
fun ElencoOrdini (modifier: Modifier = Modifier, activity: MainActivity, orders : MainActivityViewModel.MainActivityUiState) {

    Column(){

        LazyColumn(contentPadding = PaddingValues(50.dp)){
            itemsIndexed(orders.itemList) { index, item ->
                OrderItem(order = item)
            }
        }
    }

}

@Composable
fun OrderItem (order : Order) {
    Row(
        Modifier
            .fillMaxSize()
            .background(Color.LightGray)){
        Text(text = "Order #")
        Text(text = "${order.id}")

    }
}

Can someone please give a hint on how to fix it? Any tip on how to improve the code maybe? I need some guidance. Thank you very much

A.M.P.
  • 65
  • 4
  • 2
    It seems to me to be a problem related to the Room instance. You have a repository class that starts a Room instance based on a `context`, this `context` is coming from an Activity, when the Activity is recreated (by rotating the screen), the `context` changes. These are small details, but they make all the difference in the lifecycle of Android components. For example, you are passing an Activity to a ViewModel class, which literally makes this view model useless, since it will be subject to the lifecycle of UI. – Thales Isidoro Apr 27 '23 at 13:53
  • You were right! Once avoided passing context to the ViewModel everything started to work as expected. For reference I followed this guide [Android Persisting Data with Room](https://developer.android.com/codelabs/basic-android-kotlin-compose-persisting-data-room#8) – A.M.P. Apr 28 '23 at 14:07

0 Answers0