REST API & Networking

Connect your Android app to web services with HTTP, Retrofit, and Volley

HTTP REST Retrofit JSON

Table of Contents

Networking Overview

Most Android apps communicate with remote servers to fetch data, submit forms, or sync user content. REST APIs expose resources over HTTP, and libraries like Retrofit and Volley simplify making those requests from Kotlin.

Android App (UI) ↓ Repository / ViewModel ↓ Retrofit / Volley / OkHttp ↓ HTTPS → REST API Server → JSON Response
LibraryBest ForNotes
RetrofitModern REST appsType-safe, coroutines, industry standard
VolleySimple requests, cachingGoogle library, good for small apps
OkHttpLow-level HTTPUsed internally by Retrofit

1HTTP Methods

HTTP methods (verbs) tell the server what action to perform on a resource. REST APIs map CRUD operations to these standard methods.

MethodPurposeExampleIdempotent?
GETRead / retrieve dataGET /users/42Yes
POSTCreate new resourcePOST /usersNo
PUTReplace entire resourcePUT /users/42Yes
PATCHPartial updatePATCH /users/42No
DELETERemove resourceDELETE /users/42Yes

Common HTTP status codes

CodeMeaningTypical Action in App
200 OKSuccessParse response body
201 CreatedResource createdNavigate or refresh list
400 Bad RequestInvalid inputShow validation error
401 UnauthorizedNot logged inRedirect to login
404 Not FoundResource missingShow empty/error state
500 Server ErrorBackend failureRetry or show generic error

Request headers example

HTTP — Sample requestGET /api/posts HTTP/1.1 Host: jsonplaceholder.typicode.com Accept: application/json Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6... Content-Type: application/json

2REST API Basics

REST (Representational State Transfer) is an architectural style where resources (users, posts, products) are identified by URLs and manipulated using HTTP methods. Responses are usually JSON.

REST resource design

Resource HTTP Method Endpoint ───────────────────────────────────────── List posts GET /posts Get one post GET /posts/{id} Create post POST /posts Update post PUT /posts/{id} Delete post DELETE /posts/{id}

Sample JSON response

JSON — GET /posts/1{ "userId": 1, "id": 1, "title": "Hello REST API", "body": "Learning Android networking with Kotlin." }

Internet permission

XML — AndroidManifest.xml<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Practice API: Use free test endpoints like JSONPlaceholder or ReqRes while learning — no backend setup required.

3Retrofit

Retrofit is a type-safe HTTP client for Android. You define an interface with annotations, and Retrofit generates the request code. It integrates cleanly with coroutines, Gson/Moshi, and OkHttp.

Gradle dependencies

Kotlin — app/build.gradle.ktsdependencies { implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") }

API interface

Kotlin — ApiService.ktinterface ApiService { @GET("posts") suspend fun getPosts(): List<Post> @GET("posts/{id}") suspend fun getPost(@Path("id") postId: Int): Post @POST("posts") suspend fun createPost(@Body post: Post): Post @PUT("posts/{id}") suspend fun updatePost(@Path("id") id: Int, @Body post: Post): Post @DELETE("posts/{id}") suspend fun deletePost(@Path("id") id: Int): Response<Unit> } data class Post( val userId: Int, val id: Int? = null, val title: String, val body: String )

Retrofit instance

Kotlin — RetrofitClient.ktobject RetrofitClient { private const val BASE_URL = "https://jsonplaceholder.typicode.com/" private val loggingInterceptor = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } private val okHttpClient = OkHttpClient.Builder() .addInterceptor(loggingInterceptor) .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build() val api: ApiService by lazy { Retrofit.Builder() .baseUrl(BASE_URL) .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build() .create(ApiService::class.java) } }

4Volley

Volley is Google's HTTP library for Android. It handles request queuing, caching, and image loading. While Retrofit is preferred for REST APIs, Volley remains useful for simple GET/POST requests.

Gradle dependency

Kotlin — app/build.gradle.ktsdependencies { implementation("com.android.volley:volley:1.2.1") }

Initialize RequestQueue

Kotlin — MyApplication.ktclass MyApplication : Application() { lateinit var requestQueue: RequestQueue private set override fun onCreate() { super.onCreate() requestQueue = Volley.newRequestQueue(this) } companion object { fun getInstance(context: Context): MyApplication { return context.applicationContext as MyApplication } } }

StringRequest GET example

Kotlin — Volley GET requestfun fetchPostsWithVolley(context: Context, onResult: (String) -> Unit, onError: (String) -> Unit) { val url = "https://jsonplaceholder.typicode.com/posts" val queue = MyApplication.getInstance(context).requestQueue val request = StringRequest( Request.Method.GET, url, { response -> onResult(response) }, { error -> onError(error.message ?: "Request failed") } ) queue.add(request) }

JsonObjectRequest POST example

Kotlin — Volley POST with JSON bodyfun createPostWithVolley(context: Context, title: String, body: String) { val url = "https://jsonplaceholder.typicode.com/posts" val jsonBody = JSONObject().apply { put("title", title) put("body", body) put("userId", 1) } val request = JsonObjectRequest( Request.Method.POST, url, jsonBody, { response -> Log.d("Volley", "Created: $response") }, { error -> Log.e("Volley", "Error", error) } ) MyApplication.getInstance(context).requestQueue.add(request) }

5API Calls

Never block the main thread with network I/O. Use coroutines with Retrofit suspend functions, or callbacks with Volley. The Repository pattern keeps networking logic out of Activities and Fragments.

Repository pattern

Kotlin — PostRepository.ktclass PostRepository( private val api: ApiService = RetrofitClient.api ) { suspend fun getPosts(): Result<List<Post>> = safeApiCall { api.getPosts() } suspend fun getPost(id: Int): Result<Post> = safeApiCall { api.getPost(id) } suspend fun createPost(title: String, body: String): Result<Post> = safeApiCall { api.createPost(Post(userId = 1, title = title, body = body)) } }

ViewModel calling repository

Kotlin — PostViewModel.ktclass PostViewModel : ViewModel() { private val repository = PostRepository() private val _posts = MutableLiveData<List<Post>>() val posts: LiveData<List<Post>> = _posts private val _loading = MutableLiveData<Boolean>() val loading: LiveData<Boolean> = _loading private val _error = MutableLiveData<String?>() val error: LiveData<String?> = _error fun loadPosts() { viewModelScope.launch { _loading.value = true _error.value = null repository.getPosts() .onSuccess { _posts.value = it } .onFailure { _error.value = it.message } _loading.value = false } } }

Activity observing LiveData

Kotlin — MainActivity.ktclass MainActivity : AppCompatActivity() { private val viewModel: PostViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) viewModel.posts.observe(this) { posts -> adapter.submitList(posts) } viewModel.loading.observe(this) { isLoading -> binding.progressBar.isVisible = isLoading } viewModel.error.observe(this) { message -> message?.let { Toast.makeText(this, it, Toast.LENGTH_SHORT).show() } } viewModel.loadPosts() } }

6Fetching JSON Data

API responses arrive as JSON strings. Retrofit with Gson/Moshi converts them into Kotlin data classes automatically. For manual parsing, use JSONObject or JSONArray.

Data class mapping with Gson

Kotlin — User.ktdata class User( val id: Int, val name: String, val email: String, @SerializedName("avatar_url") val avatarUrl: String? = null )

Nested JSON response

JSON — Nested object{ "data": { "id": 1, "attributes": { "title": "My Post", "published": true } } }
Kotlin — Nested data classesdata class ApiResponse( val data: PostData ) data class PostData( val id: Int, val attributes: PostAttributes ) data class PostAttributes( val title: String, val published: Boolean )

Manual parsing with org.json

Kotlin — Parse JSONArray manuallyfun parsePosts(jsonString: String): List<Post> { val posts = mutableListOf<Post>() val jsonArray = JSONArray(jsonString) for (i in 0 until jsonArray.length()) { val obj = jsonArray.getJSONObject(i) posts.add( Post( userId = obj.getInt("userId"), id = obj.getInt("id"), title = obj.getString("title"), body = obj.getString("body") ) ) } return posts }

Query parameters and headers

Kotlin — Retrofit query and headerinterface ApiService { @GET("users") suspend fun searchUsers( @Query("page") page: Int, @Query("limit") limit: Int = 10 ): List<User> @GET("profile") suspend fun getProfile( @Header("Authorization") token: String ): User }

7Error Handling

Network calls can fail for many reasons — no internet, timeouts, server errors, or invalid JSON. Wrap API calls in a safe helper and map HTTP errors to user-friendly messages.

safeApiCall wrapper

Kotlin — NetworkUtils.ktsuspend fun <T> safeApiCall(apiCall: suspend () -> T): Result<T> { return try { if (!isNetworkAvailable()) { return Result.failure(NetworkException("No internet connection")) } Result.success(apiCall()) } catch (e: HttpException) { Result.failure(mapHttpError(e)) } catch (e: IOException) { Result.failure(NetworkException("Connection failed. Check your network.")) } catch (e: Exception) { Result.failure(e) } } fun mapHttpError(exception: HttpException): Exception { return when (exception.code()) { 400 -> ApiException("Invalid request") 401 -> ApiException("Please log in again") 403 -> ApiException("Access denied") 404 -> ApiException("Resource not found") 500 -> ApiException("Server error. Try again later.") else -> ApiException("Error ${exception.code()}: ${exception.message()}") } } class NetworkException(message: String) : Exception(message) class ApiException(message: String) : Exception(message)

Check network connectivity

Kotlin — isNetworkAvailable()fun Context.isNetworkAvailable(): Boolean { val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val network = connectivityManager.activeNetwork ?: return false val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) }

Retrofit Response handling

Kotlin — Check isSuccessfulsuspend fun deletePostSafely(id: Int): Result<Unit> { return try { val response = api.deletePost(id) if (response.isSuccessful) { Result.success(Unit) } else { Result.failure(ApiException("Delete failed: ${response.code()}")) } } catch (e: Exception) { Result.failure(e) } }

UI error states

Kotlin — Show error in UIsealed class UiState<out T> { object Loading : UiState<Nothing>() data class Success<T>(val data: T) : UiState<T>() data class Error(val message: String, val retry: (() -> Unit)? = null) : UiState<Nothing>() } // In Fragment/Activity: when (val state = viewModel.uiState.value) { is UiState.Loading -> showProgress() is UiState.Success -> showData(state.data) is UiState.Error -> { hideProgress() binding.errorText.text = state.message binding.btnRetry.setOnClickListener { state.retry?.invoke() } } }

8Hands-On Exercises

1

Add INTERNET permission and study the HTTP methods table — match each CRUD action to GET, POST, PUT, DELETE.

2

Explore JSONPlaceholder in a browser. Understand REST API endpoints for /posts and /users.

3

Set up Retrofit with Gson converter. Create an ApiService interface and fetch the posts list.

4

Make the same GET request using Volley StringRequest and compare the callback approach.

5

Build a Repository + ViewModel flow. Display posts in a RecyclerView with loading indicator.

6

Parse a nested JSON response into Kotlin data classes. Map a field with @SerializedName.

7

Implement error handling: show "No internet" when offline, map 404/500 codes, and add a Retry button.

REST API & Networking MCQ Practice

10 Basic MCQs 10 Advanced MCQs

10 Basic REST API & Networking MCQs

1

REST stands for?

ARemote Execution Service Tool
BRepresentational State Transfer
CReactive Event Stream Transport
DRuntime Embedded SQL Template
Explanation: REST is an architectural style for networked APIs using HTTP.
2

HTTP GET typically?

ASigns APK
BDeletes database
CRetrieves data from server
DStarts Service
Explanation: GET is idempotent and used for reading resources.
3

Retrofit is?

ACamera library
BJSON database
CLayout manager
DType-safe HTTP client for Android/Java
Explanation: Square's Retrofit converts REST API into Java/Kotlin interfaces.
4

HTTP POST used for?

ACreating or submitting data
BOnly reading cache
CGradle sync
DLayout inflation
Explanation: POST sends body data to create/update resources.
5

JSON in API responses is?

ABinary dex format
BJavaScript Object Notation text format
CSQL schema
DManifest XML
Explanation: Lightweight data interchange format parsed into objects.
6

INTERNET permission is?

AOptional for Retrofit
BRuntime dangerous permission
CRequired in manifest for network calls
DReplaced by WiFi permission
Explanation: Normal permission declared in AndroidManifest.xml.
7

HTTP 404 means?

AUnauthorized
BSuccess
CServer error always
DResource not found
Explanation: Client error — URL or resource ID doesn't exist.
8

Base URL in Retrofit set via?

ARetrofit.Builder().baseUrl(...)
Bstrings.xml only
CRoom database
DIntent filter
Explanation: All @GET/@POST paths append to base URL.
9

Volley is?

ASQL ORM
BGoogle HTTP library with request queue
CUI widget
DBluetooth stack
Explanation: Volley suits small frequent requests; Retrofit preferred for REST APIs.
10

HTTPS provides?

ANo certificates needed
BFaster than HTTP always
CEncrypted HTTP via TLS/SSL
DLocalhost only
Explanation: Always use HTTPS for production API calls.

10 Advanced REST API & Networking MCQs

11

@GET("users/{id}") path param?

A@Query only
B@Path("id") in method parameter
C@Body required
D@Header id
Explanation: @Path maps URL template segments to method args.
12

OkHttp Interceptor used for?

ASQLite migration
BLayout preview
CLogging, auth headers, retry logic
DCamera bind
Explanation: Interceptors modify requests/responses in the chain.
13

Retrofit with coroutines uses?

AMain thread blocking
BAsyncTask
CHandler only
Dsuspend fun on service interface
Explanation: CallAdapter converts Response to suspend or Flow.
14

HTTP 401 indicates?

AUnauthorized — auth required or invalid
BSuccess
CNot found
DTimeout only
Explanation: Handle with token refresh or login redirect.
15

Connection timeout handled by?

AManifest merge
BOkHttp client timeout settings
CViewBinding
DRecyclerView
Explanation: connectTimeout, readTimeout, writeTimeout on OkHttpClient.
16

@Query annotation?

APath segment
BJSON body field
CAppends ?key=value query parameters
DGradle property
Explanation: Example: @Query("page") page: Int for pagination.
17

NetworkOnMainThreadException means?

AMissing icon
BServer down
CInvalid JSON
DNetwork call on UI thread
Explanation: Use coroutines, Retrofit enqueue, or background thread.
18

Retrofit GsonConverterFactory?

AAuto JSON to Kotlin/Java objects
BEncrypts traffic
CCaches images
DGPS location
Explanation: Converter parses response body into model classes.
19

REST idempotency — PUT vs POST?

AIdentical
BPUT idempotent update; POST creates new
CPOST always idempotent
DPUT creates only
Explanation: Repeating PUT to same URI has same effect.
20

Certificate pinning?

AUse HTTP
BDisable TLS
CTrust only specific server certificates
DRoom feature
Explanation: Mitigates MITM — pin cert in OkHttp CertificatePinner.
Click an option to select, then check answers.

REST API & Networking Interview Q&A

15 topic-focused questions for interviews and revision.

1What is a REST API?easy
Answer: HTTP-based interface using resources (URLs) and methods (GET/POST/PUT/DELETE) exchanging JSON or XML.
2Retrofit setup steps.easy
Answer: Add dependencies, define data classes, create interface with @GET/@POST, build Retrofit with baseUrl and converters, create service instance.
3Difference GET vs POST.easy
Answer: GET retrieves data without body; POST submits data in body to create or process.
4Handle API errors in Retrofit.medium
Answer: Check response.isSuccessful; parse errorBody; use try/catch for IOException; map HTTP codes to user messages.
5Why not call network on main thread?easy
Answer: Blocks UI causing ANR; Android throws NetworkOnMainThreadException on strict mode.
6Explain @Path, @Query, @Body.medium
Answer: Path: URL segments. Query: ?key=val. Body: request payload object serialized to JSON.
7Volley vs Retrofit.medium
Answer: Volley: simple queue, images. Retrofit: declarative REST, coroutines, better for structured APIs.
8Add auth token to requests.medium
Answer: OkHttp Interceptor adds Authorization header to every request from SharedPreferences or token provider.
9Parse JSON without Retrofit.easy
Answer: org.json.JSONObject, JSONArray, or Gson.fromJson manually from response string.
10HTTP status codes 2xx, 4xx, 5xx.easy
Answer: 2xx success; 4xx client error (bad request, 404); 5xx server error.
11Pagination in REST API.medium
Answer: Query params page/limit or cursor; load next page on scroll with Retrofit @Query.
12Timeout and retry strategy.hard
Answer: Configure OkHttp timeouts; retry idempotent GET on failure; exponential backoff for POST carefully.
13Testing API calls.hard
Answer: MockWebServer for unit tests; interceptors for logging; fake repository in ViewModel tests.
14Cleartext traffic restriction.medium
Answer: Android 9+ blocks HTTP by default; use HTTPS or networkSecurityConfig for dev only.
15Repository pattern with API.medium
Answer: Repository abstracts Retrofit service; ViewModel calls repository suspend functions; single source of truth.