Irbisa · Cheatsheet

Android Fundamentals

Activity, Fragment, lifecycle, Intent, Manifest, configuration changes

Junior Developer · 25 questions

  1. 01

    What are the four main Android app components, and why is Application not one of them?

    Activity, Service, BroadcastReceiver and ContentProvider.

  2. 02

    Walk through the Activity lifecycle: why does setContentView() go in onCreate(), and when is onDestroy() called without onPause()/onStop()?

    onCreate → onStart → onResume bring an Activity up, onPause → onStop → onDestroy take it down.

    class HomeActivity : ComponentActivity() {  override fun onCreate(savedInstanceState: Bundle?) {    super.onCreate(savedInstanceState)    if (!session.isLoggedIn) {      startActivity(Intent(this, LoginActivity::class.java))      finish()   // next callback is onDestroy: no onStart, onResume, onPause or onStop…
  3. 03

    What happens to an Activity on screen rotation, and where do you keep state so it survives: ViewModel, onSaveInstanceState or rememberSaveable?

    Rotation is a configuration change: the Activity is destroyed and recreated with the new resources, so its fields are lost.

    class SearchViewModel(private val state: SavedStateHandle) : ViewModel() {  // survives rotation (ViewModel) and process death (saved state)  val query: StateFlow<String> = state.getStateFlow("query", "")  fun onQueryChange(q: String) { state["query"] = q }}…
  4. 04

    What kinds of Context does Android hand you, and which one must never be held by a long-lived object?

    A Context is your handle on the system: resources, preferences, starting components.

  5. 05

    Where do you put code that must run before any Activity exists, and what should never be kept there?

    In Application.onCreate(): it runs once per process, on the main thread, before any Activity, Service or receiver.

    @HiltAndroidAppclass ShopApp : Application() {  override fun onCreate() {    super.onCreate()    crashReporter.install(this)   // cheap, and useless if it starts late    ProcessLifecycleOwner.get().lifecycle.addObserver(AppForegroundObserver)…
  6. 06

    What goes into AndroidManifest.xml, and how do the manifests of your libraries end up merged into your app?

    The manifest tells the system what the app contains before any of its code runs: its components, the intents they accept, the permissions and hardware it needs.

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools">   <uses-permission android:name="android.permission.CAMERA" />  <uses-feature android:name="android.hardware.camera" android:required="false" />…
  7. 07

    What do minSdk, targetSdk and compileSdk each control, and what actually changes when you raise targetSdk?

    compileSdk decides which APIs you can compile against, minSdk the oldest Android version that can install the app, and targetSdk which platform behaviour changes the system applies to you.

    // app/build.gradle.ktsandroid {  compileSdk = 36            // APIs you can compile against  defaultConfig {    minSdk = 26              // oldest device that can install    targetSdk = 36           // behaviour changes you have tested for…
  8. 08

    You add res/values-ru/strings.xml and res/drawable-xxhdpi/. How does Android decide which one a given device gets?

    Android compares the qualifiers in each folder name with the current device configuration, discards every folder that contradicts it, and among the rest picks the one that wins in a fixed precedence order.

  9. 09

    What is an Intent: explicit vs implicit, how does the system resolve an implicit one, and how do you get a result back?

    An Intent is a message asking the system to start a component.

    // Explicit: a screen in your own appstartActivity(Intent(this, DetailActivity::class.java).putExtra("id", 42L)) // Implicit: any app that can view a web pagetry {  startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com")))…
  10. 10

    What is a Fragment, how is its lifecycle tied to the host Activity, and why does it have a separate viewLifecycleOwner?

    A Fragment is a reusable piece of UI with its own lifecycle that lives inside an Activity.

    class ProfileFragment : Fragment(R.layout.fragment_profile) {  private val viewModel: ProfileViewModel by viewModels()   override fun onViewCreated(view: View, savedInstanceState: Bundle?) {    super.onViewCreated(view, savedInstanceState)    val name = view.findViewById<TextView>(R.id.name)…
  11. 11

    This Fragment crashes after rotation with "could not find Fragment constructor". What is wrong, and how should data get into a Fragment?

    class ProfileFragment(private val userId: String) : Fragment(R.layout.fragment_profile) {  private val viewModel: ProfileViewModel by viewModels()   override fun onViewCreated(view: View, savedInstanceState: Bundle?) {    super.onViewCreated(view, savedInstanceState)    viewModel.load(userId)  }} supportFragmentManager.commit {  replace(R.id.container, ProfileFragment("42"))}

    The FragmentManager recreates fragments itself after a configuration change or process death, and it can only call the empty constructor.

  12. 12

    How do runtime permissions work on Android, and what are the normal, dangerous and signature protection levels?

    Each permission has a protection level.

    class ScannerActivity : ComponentActivity() {  private val cameraPermission = registerForActivityResult(    ActivityResultContracts.RequestPermission()  ) { granted -> if (granted) openCamera() else showCameraUnavailable() }   fun onScanClick() {…
  13. 13

    Which events trigger onPause() without onStop(), and what do a dialog, multi-window and picture-in-picture do to the Activity lifecycle?

    onPause means the Activity has lost focus but may still be visible; onStop comes only once it is fully hidden.

  14. 14

    Why do you pass objects between screens as Parcelable rather than Serializable, and why can a big Bundle throw TransactionTooLargeException?

    Extras and saved state are flattened into a Parcel and sent through Binder; Parcelable is the explicit, fast format, Serializable is reflection-based and slower.

    // build.gradle.kts: plugins { id("kotlin-parcelize") }@Parcelizedata class Address(val city: String, val street: String, val zip: String) : Parcelable startActivity(  Intent(this, CheckoutActivity::class.java).putExtra(EXTRA_ADDRESS, address)…
  15. 15

    What is process death, how do you reproduce it, and which state survives it?

    When your app is in the background, the system may kill its process to free memory.

    # 1. Open the screen, fill in the form, press Homeadb shell am kill com.example.shop # 2. The process is gone (prints nothing)adb shell pidof com.example.shop…
  16. 16

    How do two Fragments exchange data (Fragment Result API, a shared ViewModel or an interface), and when do you pick each?

    A one-shot result goes through the Fragment Result API (setFragmentResult / setFragmentResultListener); shared, ongoing state goes in a ViewModel scoped to their common owner.

    // Picker: sends a one-shot resultclass SortPickerFragment : DialogFragment() {  private fun onPicked(sort: String) {    setFragmentResult("sort_request", bundleOf("sort" to sort))    dismiss()  }…
  17. 17

    What is the difference between add() and replace() in a FragmentTransaction, what does addToBackStack() do, and when do you need childFragmentManager?

    replace() removes the fragments currently in the container and adds the new one; add() puts the new one on top and leaves the old one alive with its view.

    supportFragmentManager.commit {  setReorderingAllowed(true)  replace(R.id.container, OrderDetailFragment.newInstance(orderId))  addToBackStack("detail")      // Back returns to the list instead of closing the app}…
  18. 18

    What do commit(), commitNow() and commitAllowingStateLoss() do, and why does a commit crash with "Can not perform this action after onSaveInstanceState"?

    commit() schedules the transaction on the main thread, commitNow() runs it synchronously, and commitAllowingStateLoss() skips the saved-state check.

    // wrong: the result can arrive while the app is stoppedviewModel.result.observeForever { result ->  parentFragmentManager.commit { replace(R.id.container, ResultFragment.newInstance(result)) }} // right: events are delivered only while the view is at least STARTED…
  19. 19

    What do the launch modes standard, singleTop, singleTask and singleInstance change, and with stack A-B-C-D how do you get back to A?

    A launch mode decides whether starting an Activity creates a new instance or reuses an existing one.

    // A-B-C-D: return to the existing A, destroying B, C and DstartActivity(Intent(this, HomeActivity::class.java).addFlags(  Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)) class HomeActivity : ComponentActivity() {…
  20. 20

    What is a BroadcastReceiver, how do manifest and runtime receivers differ, and what changed for them in Android 8 and Android 14?

    A BroadcastReceiver reacts to system-wide or app events; a manifest receiver can start your process, a runtime one exists only while registered.

    class BootReceiver : BroadcastReceiver() {  override fun onReceive(context: Context, intent: Intent) {    // main thread, and the process may die right after this returns    WorkManager.getInstance(context).enqueueUniqueWork(      "resync", ExistingWorkPolicy.KEEP, OneTimeWorkRequestBuilder<SyncWorker>().build()    )…
  21. 21

    What is a ContentProvider, when do you actually need one, and how does FileProvider let another app open your file?

    A ContentProvider exposes data through content:// URIs with a query/insert/update/delete interface, and the system enforces permissions on it.

    // Manifest: FileProvider with authorities=${applicationId}.fileprovider, exported=false,// grantUriPermissions=true and meta-data FILE_PROVIDER_PATHS -> @xml/file_paths val uri = FileProvider.getUriForFile(  context, "${context.packageName}.fileprovider", pdfFile)…
  22. 22

    This code crashes when the response arrives. Why, and how do Looper, Handler and MessageQueue get work back onto the main thread?

    class ProfileActivity : AppCompatActivity() {  override fun onCreate(savedInstanceState: Bundle?) {    super.onCreate(savedInstanceState)    setContentView(R.layout.activity_profile)    val nameView = findViewById<TextView>(R.id.name)     Thread {      val user = api.loadUserBlocking()      nameView.text = user.name    }.start()  }}

    It touches a view from a background thread, which throws CalledFromWrongThreadException: only the thread that created the view hierarchy, the main thread, may change it.

  23. 23

    Find the bug: after leaving the splash screen, the app still opens the main screen two seconds later.

    class SplashActivity : AppCompatActivity() {  private val handler = Handler(Looper.getMainLooper())   override fun onCreate(savedInstanceState: Bundle?) {    super.onCreate(savedInstanceState)    setContentView(R.layout.activity_splash)    handler.postDelayed({      startActivity(Intent(this, MainActivity::class.java))      finish()    }, 2_000)  }}

    The delayed Runnable is never cancelled.

  24. 24

    How does your Kotlin code actually run on Android: what is DEX, what replaced Dalvik, and how do JIT and AOT work together in ART?

    The Kotlin compiler produces JVM bytecode, D8 (or R8 in release builds) converts it into DEX bytecode, and the Android Runtime (ART) executes it.

  25. 25

    Can one app run in several processes, and how do processes talk to each other through Binder, AIDL and bound services?

    Yes: android:process on a component runs it in a separate process with its own memory, its own Application instance and its own singletons.

    // IOrderService.aidl:  interface IOrderService { int getCount(); } class OrderService : Service() {  private val binder = object : IOrderService.Stub() {    // runs on a Binder pool thread, so it must be thread-safe    override fun getCount() = repo.count()…