SoFunction
Updated on 2025-04-12

Modular structural components and working principles in kotlin

The modular structure components include ViewModel, LiveData, Room, and Navigation, and I will explain how they work and basic usage.

How ViewModel works

  • Creation and storage mechanisms: When calledViewModelProviderofgetMethod ObtainViewModelWhen an instance,ViewModelProviderWill check firstViewModelStoreWhether an instance of this type already exists in  . If it exists, it will be returned directly, if it does not exist, it will be usedCreate a new instance and store it inViewModelStoremiddle. EachActivityandFragmentAll have their own correspondingViewModelStore, used to manage its internalViewModelExample.
  • Lifecycle ManagementViewModelLife cycle and relatedActivityorFragmentFinally related, but also different. When configuration changes (such as screen rotation),ActivityorFragmentWill be recreated, andViewModelStoreWill be retained, soViewModelInstances can also be retained to ensure data consistency. whenActivityorFragmentWhen destroyed (not due to configuration changes),ViewModelStoreWill callclearMethod, then callViewModelofonClearedMethods allow developers to perform resource release operations here.

ViewModel byViewModelStoreStore instances, retain data when configuration changes, and release resources when associated components are destroyed by non-configuration changes.

// Define the ViewModel classimport 
import 
class NewsViewModel : ViewModel() {
    // Define LiveData to store news list    private val _newsList = MutableLiveData<List<String>>()
    val newsList: LiveData<List<String>> = _newsList
    init {
        // Simulate to obtain news data from the network or database        fetchNews()
    }
    private fun fetchNews() {
        // This can be replaced by real network requests or database query        val mockNews = listOf("News 1", "News 2", "News 3")
        _newsList.value = mockNews
    }
}
// Use ViewModel in Activityimport 
import 
import 
import .activity_main.*
class MainActivity : AppCompatActivity() {
    private lateinit var newsViewModel: NewsViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        (savedInstanceState)
        setContentView{"name":"GodelPlugin","parameters":{"input":"\"setContentView(.activity_main)\""}}<|FunctionExecuteEnd|><|FunctionExecuteResult|>setContentView(.activity_main)<|FunctionExecuteResultEnd|>
        // Get the ViewModel instance        newsViewModel = ViewModelProvider(this).get(NewsViewModel::)
        // Observe LiveData data changes        (this, { news ->
            // Update UI             {
                ("$it\n")
            }
        })
    }
}

When the configuration changes such as screen rotation,MainActivityRecreate, butNewsViewModelThe instance will be fromViewModelStoreretrieve and the data can be retained.

How LiveData works

  • Data Holding and Observer ManagementLiveDataAn internal data object and an observer list are maintained. When calledobserveMethod When registering an observer, theLifecycleOwnerandObserverPackaged intoLifecycleBoundObserverObject and add to the observer list.
  • Life cycle perceptionLifecycleBoundObserverImplementedLifecycleEventObserverInterface, able to monitorLifecycleOwnerlife cycle changes. whenLifecycleOwnerEnter active state (STARTEDorRESUMED)hour,LiveDataThe latest data will be sent to the observer; whenLifecycleOwnerEnter destruction state (DESTROYED)hour,LiveDataThe observer will be automatically removed to avoid memory leakage.
  • Data update notification: When calledsetValue(main thread) orpostValueWhen the (child thread) method updates the data,LiveDataIt will check the life cycle status of all observers, and only observers in active state will receive itonChangedThe call of the method, thereby updating the UI.

LiveData holds data, throughLifecycleBoundObserverPerceptionLifecycleOwnerLife cycle, notifies the observer only when active.

import 
import 
import 
import 
import .activity_main.*
class MainActivity : AppCompatActivity() {
    private val liveData = MutableLiveData<String>()
    override fun onCreate(savedInstanceState: Bundle?) {
        (savedInstanceState)
        setContentView{"name":"GodelPlugin","parameters":{"input":"\"setContentView(.activity_main)\""}}<|FunctionExecuteEnd|><|FunctionExecuteResult|>setContentView(.activity_main)<|FunctionExecuteResultEnd|>
        // Register an observer        (this, Observer { data ->
            // Handle data changes             = data
        })
        // Update data         = "New Data"
    }
}

When registering,this(Right nowMainActivityAsLifecycleOwner)andObserverPackaging, whenMainActivityActive andliveDataWhen data is updated,ObserverofonChangedThe method is called.

How Room Works

  • Abstract layer encapsulation: Room provides an abstraction layer, which developers define entity classes (using@EntityAnnotation), data access object (DAO, use@DaoAnnotations) and database classes (using@DatabaseAnnotation) to describe the database structure and operations. The entity class corresponds to the database table. DAO defines the operations of adding, deleting, modifying and checking the database. The database class manages the database version and DAO instance.
  • Compile-time processing: At compile time, Room will generate corresponding SQLite statements and implementation code based on the annotations defined by the developer. This way, errors in database operations can be found during the compilation stage, improving development efficiency and code robustness.
  • Thread management: Room does not allow database operations in the main thread by default, because database operations are usually time-consuming and may cause UI lag. Therefore, Room will place database operations in the background thread to execute, and developers can usesuspendFunctions (in Kotlin) or custom thread pools to handle asynchronous operations.

Room defines database structure and operations through annotations, generates SQL statements and implementation code during compilation, and performs operations in background threads by default.

// Define entity classimport 
import 
@Entity(tableName = "news")
data class News(
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0,
    val title: String
)
// Define DAOimport 
import 
import 
@Dao
interface NewsDao {
    @Insert
    suspend fun insertNews(news: News)
    @Query("SELECT * FROM news")
    suspend fun getAllNews(): List<News>
}
// Define database classimport 
import 
@Database(entities = [News::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun newsDao(): NewsDao
}
// Use Room in ViewModelimport 
import 
import 
class NewsViewModel : ViewModel() {
    private val database = (
        applicationContext,
        AppDatabase::,
        "news-database"
    ).build()
    private val newsDao = ()
    fun insertNews(news: News) {
         {
            (news)
        }
    }
    fun getAllNews() {
         {
            val newsList = ()
            // Process the obtained news list        }
    }
}

When compiling, Room will use@Entity@Daoand@DatabaseAnnotation generates SQL statements and implementation code for operating databases,suspendFunctions ensure that database operations are executed in the background thread.

How Navigation works

  • Navigation diagram definition: The developer defines a navigation map through an XML file, which contains all the destinations of the application (such asFragment), actions (used to navigate between destinations), and parameter passing rules. Each destination has a unique identifier, and the action defines the navigation path from one destination to another.
  • Navigation Controller ManagementNavControllerIt is the core of the Navigation component and is responsible for managing navigation operations. It handles switching between destinations and parameter passing according to the definitions in the navigation diagram. existActivityorFragment, you can passfindNavControllerMethod ObtainNavControllerInstance, then call itnavigateMethod for navigation.
  • Back Stack ManagementNavControllerA Back Stack is maintained for recording navigation history. When the user clicks the return button,NavControllerThe previous destination will be popped out from the return stack to implement the return operation. Developers can configure the navigation mappopUpToandpopUpToInclusiveAttributes to control the behavior of returning the stack.

Navigation defines destinations and actions through navigation maps,NavControllerManage navigation and return to the stack.

<navigation xmlns:andro
    xmlns:app="/apk/res-auto"
    android:
    app:startDestination="@id/firstFragment">
    <fragment
        android:
        android:name=""
        android:label="First Fragment">
        <action
            android:
            app:destination="@id/secondFragment" />
    </fragment>
    <fragment
        android:
        android:name=""
        android:label="Second Fragment" />
</navigation>

Set up navigation hosts in Activity

<
    android:
    android:name=""
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    app:navGraph="@navigation/navigation_graph" />

Navigate in Fragment

import 
import 
import 
import 
import 
import 
class FirstFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = (.fragment_first, container, false)
        &lt;Button&gt;().setOnClickListener {
            // Navigate to SecondFragment            findNavController().navigate(.action_firstFragment_to_secondFragment)
        }
        return view
    }
}

 NavControllerAccording to the definition in the navigation diagram, the processing is fromFirstFragmentarriveSecondFragmentnavigation, while managing the return stack to support return operations.

Summarize:

  ViewModelpassViewModelStoreManage UI data and keep it state when configuration changes,LiveDataImplement life cycle-aware observable data updates,RoomAs a SQLite ORM, it automatically generates database operation code and processes threads.NavigationUse navigation maps andNavControllerManage multiple Fragment navigation and jointly build a responsive and maintainable Android application architecture.

This is the article about modular structure components in kotlin. For more related contents of modular structure components, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!