Is it weird to be currently using single activity ...
# compose
c
Is it weird to be currently using single activity with multiple fragments and now I want to convert my activity to not have xml anymore and to instead just
setContent{ }
? In order to do this it looks like I'll have to use
AndroidView
to host a
FragmentContainerView
. Or does this all seem like a bad idea and should I just keep my 10 lines of xml for the activity layout. 😅
i
You could use
AndroidViewBinding
to inflate the layout; that works fine with
FragmentContainerView
inflated fragments
c
Hm. You kinda lost me with the AndroidViewBinding bit. This is what I currently have
Copy code
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AndroidView(
                factory = { context ->
                    FragmentContainerView(context).apply {
                        //Figure out how to set these programatically
//                        android:name="androidx.navigation.fragment.NavHostFragment"
//                        android:id="@+id/nav_host_fragment"
//                        app:defaultNavHost="true"
//                        app:navGraph="@navigation/nav_graph"
                    }
                }
            )
        }
    }
Not sure where AndroidViewBinding fits into it.
i
I mean the Composable function
AndroidViewBinding
from the
ui-viewbinding
artifact: https://developer.android.com/jetpack/compose/interop/interop-apis#views-in-compose (the last example of that section)
c
Oooh! TIL Thanks. Before I got your response I actually tried this and it seemed to work. Any pro/cons?
Copy code
setContent {
    AndroidView(
        factory = { context ->
            LayoutInflater.from(context).inflate(R.layout.only_my_fragment_container_view, null)
        }
    )
}
i
Only
AndroidViewBinding
has specific fixes around hosting a fragment in Compose (cleaning up the fragment if you remove it from your Compose hierarchy, etc), so you might get away with that super basic usage of a single static fragment, but it wouldn't work as well for a more complicated use case
Nor would that approach work if your Compose hierarchy was nested within another fragment (something only
AndroidViewBinding
handles correctly)
c
Ah. That's really great to know. Is there a bug or docs or something I could reference that says "don't use FragmentContainerView with AndroidView composable"?
Just want my PR to include why I'm enabling ViewBinding and using AndroidViewBinding composable instead of AndroidView. I guess I could just screenshot your message here. 😄
i
🙏 1
c
One last question. I had this code in my onCreate() before
Copy code
val navHostFragment =
    supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.navController
I don't actually think I need navController, but I guess off the cuff, am I walking into any trouble if I need to grab my navcontroller?
i
That would still work
👍 1
a
Well I've started to migrate all my navigation to compose-navigation. It's been a lot of work already since we have tons of screens, but I'm glad we've started now.
I've tried all kinds of approaches and workarounds for the Fragment-based compose navigations, including that one. Thought it would be smarter long term to use the compose version now
c
Can compose navigation be used with fragments though? i.e. Can I have compose destinations, fragment destinations, and activity destinations? I haven't used compose navigation because I thought it was compose destinations only.
a
My point is my team decided to get rid of all our fragments and move to pure compose
You don't need compose nav for starting an activity. And I think composable with an fragment inside might work too if you really need it
c
@allan.conda oh I was confused because you said "Well I've started to migrate all my navigation to compose-navigation. It's been a lot of work already since we have tons of screens, but I'm glad we've started now." so it sounds like you completely switched to compose-nav but are slowly migrating all screens individually to compose.
a
Yep
👍 1
i
As long as you use
AndroidViewBinding
for inflating your fragments, embedding fragments in Compose works well enough to be a good transitional step
c
Perfect. It's definitely transitional for us as our team is already accustomed to using AAC view models, exposing state as a single stream, etc so we're really just trying to move to composables as we already use fragment based nav. Then after all fragments are composables we'll start work on moving to pure compose with compose nav. Then we'll remove AAC viewModels. Etc
👋 Hi again Ian
Copy code
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContent {
        MaterialTheme {
                AndroidViewBinding(MyFragmentContainerViewBinding::inflate) {}
        }
    }

    val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
}
This crashes on findFragmentById. I'm assuming I'm doing something very wrong here?
i
setContent
doesn't execute its lambda immediately; you'd want to do that work in that empty lambda of the
AndroidViewBinding
c
Gotcha. Alright, I just dropped it into the update lambda and now it works. 🤦 So much to learn! But my app is working! Ahhhh! Thanks Ian!
i
What is 'all the existing fragment UX and handling' mean in your case?
b
recyclerview initialization, adapter coordination, navigation events
basically trying to rescaffold our app to be compose based so we can iterate through the various tab views to be compose
have the scaffold swapped out and navigation handled to tab destinations, now im trying to bridge existing fragments into AndroidView/AndroidViewBinding
without rewriting them (which may not be possible)
i
I'm afraid I'm even more confused now. This thread was about hosting a fragment inside your Compose hierarchy. RecyclerView initialization, adapter coordination, navigation events are all things that go inside a Fragment. Nothing outside of the Fragment should be touching things owned by the fragment?
b
right
so
Copy code
@Composable
fun Grid() {
    AndroidViewBinding(FragmentPlanoGridBinding::inflate) {
        // binding.something.setOnClickListener { }
    }
}
would still need to be done here im assuming?
i
If you have things other than your fragment in that layout, yep