Fragments in Apollo Kotlin
Note: This article describes the behavior of fragments when using the default
operationBased
codegen in Apollo Kotlin. For theresponseBased
codegen, see this page.
Apollo Kotlin supports both forms of GraphQL fragments:
Named fragments, which enable you to reuse a set of fields across multiple operations
Inline fragments, which enable you to access fields of polymorphic types
Named fragments
Take a look at the following GraphQL definitions:
1# Declaration of named fragment
2fragment launchFragment on Launch {
3 id
4 site
5 mission {
6 name
7 }
8}
9
10query LaunchDetails($id:ID!) {
11 launch(id: $id) {
12 # Usage of named fragment
13 ...launchFragment
14 }
15}
Based on the fragment
definition, Apollo Kotlin generates the following LaunchFragment
class that you can reuse in different queries:
1data class LaunchFragment(
2 val id: String,
3 val site: String?,
4 val mission: Mission?
5)
Generated models for operations that use this fragment have a .launchFragment
property for accessing the fragment's fields:
1println("Mission site: ${launch.launchFragment?.site}")
The
launchFragment
property isnull
if the returned object is not aLaunch
.
You can reuse the fragment in any number of operations:
1 # ...previous definitions...
2
3query LaunchList {
4 launches {
5 launches {
6 ...launchFragment
7 }
8 }
9}
You can even use a fragment in operations that are defined in a different .graphql
file from the fragment itself. This is because Apollo Kotlin codegen merges all .graphql
files in to a single file before generating models.
Inline fragments
Take a look at this query definition that uses two inline fragments:
1query HeroForEpisode($ep: Episode!) {
2 hero(episode: $ep) {
3 name
4 ... on Droid {
5 primaryFunction
6 }
7 ... on Human {
8 height
9 }
10 }
11}
For this operation, Apollo Kotlin generates a Hero
class that contains OnDroid
and OnHuman
nested classes. Hero
also includes onDroid
and onHuman
fields that enable you to access fields that are specific to Droid
and Human
:
1println("Droid primaryFunction: ${hero.onDroid?.primaryFunction}")
2println("Human height: ${hero.onHuman?.height}")
These
on<ShapeName>
fields (onDroid
andonHuman
) arenull
if the returned object is not the corresponding type.