0

I'm trying to clean-up my code and eliminate View Models where not necessary.

I'd like to be able to access itemList, filtering, and itemListFiltered in my HomeScreen function without explicitly passing the MainViewModel as a parameter, but I can't figure out how to do it.

I tried using itemList = model::itemList but Android Studio gives error: Type mismatch. Required: List<Int> Found: KProperty0<SnapshotStateList<Int>>

View Model

class MainViewModel : ViewModel() {

    val itemList = mutableStateListOf<Int>()

    val filtering = mutableStateOf<Boolean>(false)
    val itemListFiltered = mutableStateListOf<Int>()

    fun addItem(item: Int) {
        itemList.add(item)
    }

    fun clearItemList() {
        itemList.clear()
    }

    fun filterListGreaterThan(greaterThan: Int) {
        itemListFiltered.clear()
        itemList.forEach { item ->
            if (item > greaterThan) itemListFiltered.add(item)
        }
    }

    init {
        clearItemList()
    }   // End Initializer

}

Home Screen Scaffolding

@Composable
fun HomeScreen(
    model: MainViewModel        // <-- How do I eliminate this
) {

    val scope = rememberCoroutineScope()
    val scaffoldState = rememberScaffoldState(rememberDrawerState(DrawerValue.Closed))

    Scaffold(
        scaffoldState = scaffoldState,
        topBar = { TopBar(scope, scaffoldState) },
        floatingActionButtonPosition = FabPosition.End,
        floatingActionButton = {
            FloatingActionButton(
                onAddItem = model::addItem
            ) },
        drawerContent = {
            DrawerContent(
                onAddItem = model::addItem,
                onResetList = model::clearItemList
            ) },
        drawerGesturesEnabled = true,
        content = {
            Content(
                itemList = model.itemList,      // <-- How do I pass this itemList without model?
                onAddItem = model::addItem
            ) },
        bottomBar = { BottomBar() }
    )

}

Can you help me figure out how to do that?

Thanks for your help!

SqueezeOJ
  • 441
  • 7
  • 17

1 Answers1

1

Pass it just like that...

model.itemsList

The :: symbol doesn't work how you seem to think it does. Consider it to be used for static non-changing variables/methods. Like you could use model::addItem or model::clearItemList since they are just public methods and do not hold a value.

Richard Onslow Roper
  • 5,477
  • 2
  • 11
  • 42
  • Read the official docs for `::`, or maybe refer to [this](https://stackoverflow.com/a/52463295/15880865) SO answer. – Richard Onslow Roper May 12 '22 at 22:41
  • Thanks for the help. I think was getting hung-up on eliminating the View Model parameter. So, what is the difference between ``onClick = { onAddItem((1..99).random()) }`` and ``onClick = { model.addItem((1..99).random()) }``? Why is one any better than the other? – SqueezeOJ May 13 '22 at 00:49
  • 1
    There's no difference in execution. There former is better than the latter because it follows the 'separation-ofconcerns' principle. Basically, any portion of your app should not have access to more info than it needs to work properly. This keeps the code easy to refactor as well as test. If you wished to test a Composable that takes an entire model, you will need a pseudo model at runtime, whereas one that accepts a lambda as a parameter is easy to test and maintain. It also prevents any unnecessary modifications of the model's properties by every Composable it is passed to. – Richard Onslow Roper May 13 '22 at 01:35
  • 1
    Separation of concerns* – Richard Onslow Roper May 13 '22 at 02:49