Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing Network Operations in Android Using MVVM and Retrofit

Tech 1

Implementing network operations within the Model-View-ViewModel (MVVM) architecture requires a clear separation of concerns. The repository acts as the single source of truth for data, the ViewModel manages UI-related state, and the View layer observes state changes with out handling business logic directly.

Defining the Network Client and API Interface

Begin by establishing the network configuration. Instead of scatering builder logic, encapsulate Retrofit initialization within a dedicated client module.

object NetworkProvider {
    private const val BASE_URL = "https://api.example.com/v1/"
    
    val retrofitClient: Retrofit by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(OkHttpClient.Builder().build())
            .build()
    }
}

interface ContentEndpoint {
    @GET("articles")
    suspend fun fetchLatestContent(): List<ArticleEntry>
}

Building the Data Repository

The repository handles raw network calls, error boundaries, and transforms responses into a consumable format. Wrapping results in a sealed interface provides type-safe state management for the upper layers.

sealed class DataState<out T> {
    data class Success<T>(val payload: T) : DataState<T>()
    data class Error(val exception: Throwable) : DataState<Nothing>()
    object Loading : DataState<Nothing>()
}

class ArticleRepository {
    private val apiService = NetworkProvider.retrofitClient.create(ContentEndpoint::class.java)

    fun requestContent(): Flow<DataState<List<ArticleEntry>>> = flow {
        emit(DataState.Loading)
        try {
            val result = apiService.fetchLatestContent()
            emit(DataState.Success(result))
        } catch (ex: Exception) {
            emit(DataState.Error(ex))
        }
    }.flowOn(Dispatchers.IO)
}

Constructing the ViewModel

The ViewModel bridges the repository and the UI. It exposes an immutable stream of state and provides a public function to trigger the fetch operation.

class MainScreenViewModel : ViewModel() {
    private val repo = ArticleRepository()
    private val _uiState = MutableStateFlow<DataState<List<ArticleEntry>>>(DataState.Loading)
    val uiState: StateFlow<DataState<List<ArticleEntry>>> = _uiState.asStateFlow()

    fun loadContent() {
        viewModelScope.launch {
            repo.requestContent().collect { state ->
                _uiState.value = state
            }
        }
    }
}

Connecting the View Layer

The Activity or Fragment observes the StateFlow and reacts to state transitions. Lifecycle-aware collection ensures that UI updates only occur when the component is active.

class MainActivity : AppCompatActivity() {
    private val vm: MainScreenViewModel by viewModels()
    private lateinit var adapter: ContentAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        adapter = ContentAdapter()
        findViewById<RecyclerView>(R.id.recycler_view).adapter = adapter

        vm.loadContent()

        lifecycleScope.launch {
            vm.uiState.collect { state ->
                when (state) {
                    is DataState.Loading -> showProgressIndicator()
                    is DataState.Success -> {
                        hideProgressIndicator()
                        adapter.submitList(state.payload)
                    }
                    is DataState.Error -> {
                        hideProgressIndicator()
                        displayErrorMessage(state.exception.message)
                    }
                }
            }
        }
    }
}

This structure decouples networking from presentation logic, ensuring that data flows unidirectionally. The repository isolates HTTP concerns, the ViewModel handles configuration changes and state exposure, and the view layer remains purely declarative, reacting only to emitted state objects.

Tags: Android

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.