Theory
Fetch and send, the two calls you need
Everything comes together now. FestConnect Mobile fetches the events list (a GET) and sends a new registration (a POST), both to a REST API, using Volley, parsing the JSON, and handling the response. This final lesson wires REST, JSON, and Volley into the two requests you will make most.
GET reads; POST writes. In both, Volley runs the call off the UI thread and hands you the result in a callback, where you either use the data or handle the error. Master these two, and you can consume almost any web API from Android.
Theory
A GET request: fetch the events
A GET retrieves data. You create a Volley request with Request.Method.GET, the endpoint URL, and (for GET) a null body, plus your success and error listeners.
When it succeeds, the response arrives, already parsed for a JsonObjectRequest, as a JSONObject (or JSONArray), which you then read using the parsing you learned: pull out the events array, loop it, extract each name and seats, and update the UI. So a GET is: send to the endpoint, receive JSON, parse it, display it. This is how the app shows a live list from a remote server.
Practical
GET the events, handle the response
val getEvents = JsonObjectRequest(
Request.Method.GET, "https://api.example.com/events", null,
{ response -> // success
val arr = response.getJSONArray("events")
for (i in 0 until arr.length()) {
val e = arr.getJSONObject(i)
addToList(e.getString("name"), e.getInt("seats"))
}
},
{ error -> showError("Could not load events") } // error handling
)
queue.add(getEvents)Practical
A POST request: send a registration
// Build the JSON body to send
val body = JSONObject().apply {
put("studentName", "Riya")
put("eventId", 5)
}
val postReg = JsonObjectRequest(
Request.Method.POST, "https://api.example.com/registrations", body,
{ response -> showMessage("Registered!") }, // success
{ error -> showError("Registration failed") } // error handling
)
queue.add(postReg) // POST sends 'body' to the server, which processes itFormula
Always handle both success and error
Every request has two possible outcomes, and you handle both. The success listener receives the response: use or parse the data and update the UI. The error listener receives a VolleyError: show the user a clear message, and (if useful) inspect the error for a status code or network cause.
Never write only the success path. Networks fail, servers return errors, tokens expire, and an app that ignores the error listener leaves users staring at a frozen or blank screen when something goes wrong. Handle the error every time: a failed request should produce a helpful message, not silence. Success and failure are both part of the request.
Quiz
In FestConnect Mobile, fetching the events list versus submitting a new registration to the API use which HTTP methods, respectively?
- POST to fetch, GET to submit
- GET to fetch the events (read), and POST to submit the registration (create/send)
- Both use GET
- Both use DELETE
Show the answer
GET to fetch the events (read), and POST to submit the registration (create/send)
Fetching (reading) the events list is a GET request, and submitting (creating/sending) a new registration is a POST request, matching REST conventions: GET reads, POST creates/sends. Option A reverses them, which would misuse the methods (you do not POST to merely read, nor GET to send new data). Option C is wrong: submitting a registration sends data to create something, which is POST, not GET. Option D is wrong: DELETE removes a resource, neither fetching nor submitting. Match the method to the intent: GET to fetch data, POST to send/create data, and handle both success and error in the callbacks.
Think first
Why must you always handle the error case, not just success?
The happy path works in testing. Why is handling the error listener just as important as the success listener? Then tap.
Show the answer
Because network requests FAIL regularly in the real world, and an app that only handles success leaves users confused, stuck, or staring at a broken screen whenever anything goes wrong, which is often. During development on a fast, reliable connection, the happy path seems like all that matters, the request succeeds, you show the data, done. But real users are on flaky mobile networks, in tunnels, with expired tokens, hitting servers that are temporarily down, overloaded, or returning errors. In all those cases the request FAILS, and if you wrote only a success listener, nothing happens: no data appears, no message shows, the spinner may spin forever, and the user has no idea whether to wait, retry, or give up. That is a frustrating, broken experience. Handling the error listener lets you respond gracefully: show a clear message ('Could not load events, check your connection'), offer a retry, hide the loading indicator, or fall back to cached data. You can even inspect the VolleyError for a status code to tailor the response (401 means the session expired, so prompt re-login; 404 means the resource is gone; a network error means connectivity). Robust apps treat failure as a NORMAL, expected outcome to be handled, not an edge case to ignore. This is the same discipline you met with Firebase auth errors and Task failures: always handle both outcomes. Users judge an app by how it behaves when things go wrong, so handling errors well is not optional polish, it is core quality. Plan for failure; it will happen.
Summary
Key takeaways
- GET fetches data from an endpoint; POST sends data to it, the two everyday API calls.
- A GET (Request.Method.GET, null body) returns JSON you parse in the success listener and display.
- A POST (Request.Method.POST with a JSONObject body) sends data the server processes, and responds.
- Both take a success listener (use/parse the data) and an error listener (handle failures).
- Always handle both outcomes: on error, show a clear message and optionally inspect the VolleyError for a status code.
- This ties together REST (methods), JSON parsing, and Volley into real API calls from Android.
- Memory hook: GET to fetch, POST to send; handle success AND error every time.