# compose

Neal Sanche

02/26/2021, 5:03 AM
Would it be a bad thing to try and stick a viewModel into a CompositionLocalProvider so that I don't have to pass it to all of my composables? I seem to be passing the main viewmodel all over the place, and I'm not liking doing this. I'd love some advice on this. I get the feeling I'm missing something. Pass data down, and events up. But I guess a ViewModel is actually not data, it's a data holder. So, does it make sense to be passing it down?

Zach Klippenstein (he/him) [MOD]

02/26/2021, 5:14 AM
I would expect most of your composables to not know about the view model, but only either 1) know about smaller subsets of data that they actually need to configure themselves, or 2) have slots (composable function parameters) that your screen composable could pass viewmodel data down through lambda captures
💯 2

Neal Sanche

02/26/2021, 5:28 AM
The app I'm writing processes images, and these images need to be displayed. So I'm really struggling with where to put the images, since part of the processing is done as outputs of camera 2 Android views. So it's a bit more interconnected than just simple passing data down to views. Problem with this is trying to stop inadvertent renders. I was having a lot of problems where parts of the screen seemed to be rendering because the image state was changing, and it really didn't need to. Obviously I'm likely doing something wrong here.
For now I've done this:
Copy code
val LocalImageViewModel = staticCompositionLocalOf<ImageViewModel> {
    error("LocalImageViewModel value not available.")
and in my setContent, I've done this:
Copy code
CompositionLocalProvider(LocalImageViewModel provides imageViewModel) {
                        // A surface container using the 'background' color from the theme
                        Surface(color = MaterialTheme.colors.error) {
And then I can get the viewmodel wherever I need it in the composable tree. But Maybe this is not what I should be doing, and instead, maybe I should be making state out of the things inside the viewModel that need to be passed down, and just using raw data values for displaying everything.


02/26/2021, 3:14 PM
@Zach Klippenstein (he/him) [MOD] is exactly right. Your composable functions should be stateless functional transforms from data->UI. You should avoid CompositionLocals like the plague (much like you would avoid a global variable or a ThreadLocal), because (among other things) they create implicit dependencies and implicit API for all composables that transitively utilize them. Assuming you're talking about AAC ViewModels, you should avoid using them as part of your parameter type, since they constrain your Composables to use within an Android context (making it harder to unit test, harder to share with Desktop, harder to reuse, etc).
So it's a bit more interconnected than just simple passing data down to views.
This indicates that you're not yet thinking about Compose correctly. If anything about your data flow is "more interconnected than just simple passing data down" then you're thinking about it incorrectly and should rework your data flow.

Neal Sanche

02/26/2021, 4:12 PM
Yes, @jim I know that you're right. That's why I'm asking these questions. I suspect what is leading me down this rabbit-hole is the app I'm trying to make includes an Android CameraX CameraView and a PreviewView, and it is actually producing the state I want to display, so I'm getting mixed up in the side-effects of that. I really want to know how I'd separate the concerns for that. I'll keep trying to work it out. I'll get rid of the local provider and try to work out a cleaner data -> UI flow for this small app.
👍 1
I think I'm going to ditch the
and simply just create a flow of images from the selected camera. That can live in Android land, and can be passed down into the composables. And I can also hope that CameraX gets a nice set of composable functions at some point in the future.