9. Write your first mutation
In this section, you will write your first mutation to log in to the backend. A mutation is used to change data on your server. Here the login mutation will create a session based on your email address.
Note: The way you log in to this particular server might differ from the way you log in with your own server. Login is often handled by middleware, or a layer totally separate from GraphQL, like Oauth. Also note that a typical authentication flow should require a password but for this tutorial, anyone is allowed to book flights with a valid email address!
Prototype your mutation in GraphQL Playground
Open GraphQL Playground and select the login
mutation in the docs tab on the right:
This mutation takes a single argument, the email
address of the person being logged in. Unlike many GraphQL operations that return objects which need to have fields selected, the login
mutation returns only a single string.
Type the following mutation in GraphiQL:
1mutation Login($email: String) {
2 login(email: $email)
3}
If you hit Play, you should get a null
login:
This is expected, because you didn't specify your email. To do so, add it to the Query Variables in the lower-left pane of GraphQL Playground:
1{ "email": "me@example.com" }
Press the Play button, and you'll get an actual response:
Add the mutation to the project
Now that your mutation is working, add it to your project. Create a file named Login.graphql
next to schema.json
and your other GraphQL files and paste the contents of the mutation:
1mutation Login($email: String) {
2 login(email: $email)
3}
Build your project to generate the LoginMutation
class.
Connect the Submit button to your mutation
Open LoginFragment.kt
and like you did for the other fragments, override onViewCreated
. Add a click listener and some checks to verify that the email is a valid email:
1 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
2 super.onViewCreated(view, savedInstanceState)
3
4 binding.submitProgressBar.visibility = View.GONE
5 binding.submit.setOnClickListener {
6 val email = binding.email.text.toString()
7 if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
8 binding.emailLayout.error = getString(R.string.invalid_email)
9 return@setOnClickListener
10 }
From the click listener, display the ProgressBar and execute the query with the email the user just entered:
1 binding.submitProgressBar.visibility = View.VISIBLE
2 binding.submit.visibility = View.GONE
3 lifecycleScope.launchWhenResumed {
4 val response = try {
5 apolloClient.mutate(LoginMutation(email = Input.fromNullable(email))).await()
6 } catch (e: Exception) {
7 null
8 }
Handle errors if needed:
1 val login = response?.data?.login
2 if (login == null || response.hasErrors()) {
3 binding.submitProgressBar.visibility = View.GONE
4 binding.submit.visibility = View.VISIBLE
5 return@launchWhenResumed
6 }
Finally if everything is successful, store the login and go back to the previous screen:
1 User.setToken(requireContext(), login)
2 findNavController().popBackStack()
3 }
4 }
5 }
User
is a helper class that saves the token in EncryptedSharedPreference. This is the reason why this tutorial uses API level 23+. Apollo Android itself supports API levels 19+.
Test the login
Go the details fragment, click Book and in the Login fragment, enter your email and click Submit. You now have a token that allows you to authenticate your queries.
In the next section, you will authenticate your queries.