Architecture Components Flashcards

1
Q

What is the dependency for implementing viewmodels?

A

In build.gradle(Module)

implementation ‘androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0’

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Where is the best place to perform tasks when an app launches?

A

The init block of the ViewModel

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What are the benefits of using a ViewModelProvider? (3)

A

ViewModelProvider returns an existing ViewModel if one exists, or it creates a new one if it does not already exist.

ViewModelProvider creates a ViewModel instance in association with the given scope (an activity or a fragment).

The created ViewModel is retained as long as the scope is alive. For example, if the scope is a fragment, the ViewModel is retained until the fragment is detached.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

When is the callback ViewModel.onCleared( ) called?

What does it do?

A

When a Fragment is detached, the ViewModel is destroyed.

onCleared( ) is called just before this happens - to clean up resources.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Demonstrate the steps to implement a ViewModel from a ViewModelFactory that is instantiated in a Fragment and passes in a parameter from navArgs.

A
1. Create ViewModel
class MyViewModel(val myArg: Type): ViewModel( ){
}
2. Create ViewModelFactory:
class MyViewModelFactory(private val myArg: Type): ViewModelProvider.Factory{
  override fun  create(modelClass: Class): T {
   if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
       return MyViewModel(myArg) as T
   }
   throw IllegalArgumentException("Unknown ViewModel class")
}
}
  1. Instantiate both of the above in the fragment:
    private lateinit var viewModel: MyViewModel
    private lateinit var viewModelFactory: MyViewModelFactory

viewModelFactory = MyViewModelFactory(MyFragmentArgs.fromBundle(requireArguments()).myArg)
viewModel = ViewModelProvider(this, viewModelFactory)
.get(MyViewModel::class.java)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q
  1. What two arguments are taken by LiveData.observe( )?
  2. Where should they be assigned?
  3. What should be assigned as the first argument?
A
  1. LifecycleOwner and Observer(where logic is performed when the value changes)
  2. LiveData.observe( ) should be called in Fragment.onCreateView( )
  3. The viewLifecycleOwner should be passed as the Owner
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What is the Codelabs way to ensure encapsulation of LiveData values?

A

private val _myVar = MutableLiveData^Type^( )

val myVar: LiveData^Type^ get( ) = _myVar

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

In a nutshell, what is the observer pattern?

When using LiveData, what is the Observable and what is the Observer?

A

An observable is an object that notifies observers about the changes in its state.

LiveData object is the Observable. The Observer is the lambda function in Fragment.onCreateView( )

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

If using a LiveData to trigger navigation, what must you remember to do immediately after the navigation logic has been defined?

A

Call a viewModel function that resets the LiveData triggering the navigation back to its original value

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Why is Transformations.map( ) used?

How is Transformations.map( ) used?

What else is it important to remember about Transformations.map( ) ? (2)

A

Why:
It takes one LiveData object, manipulates it, and returns a new LiveData object

How:
val newLiveData = Transformations.map( oldLiveData) {value -^ //manipulate value, potentially to a different Type}

Important to remember:
1. Executed on main thread, so no long-running tasks

  1. Not executed unless an observer is observing the returned LiveData object
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Why extend AndroidViewModel instead of just ViewModel?

A

AndroidViewModel can provide application context by calling getApplication().

It is, however, problematic for unit testing because context is part of the Android lifecycle.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q
  1. What is work Manager for?
  2. What does WorkManager use for backward compatibility?
  3. What is the dependency?
A
  1. Background work that:
    - is deferrable - not required immediately
    - requires guaranteed execution - the task will run even if the app exits or the device restarts
  2. WorkManager is compatible back to API 14 (Android 4.0, 2011)
    - Uses JobScheduler on API23 (Android 6.0, 2015) and above
    - Uses a combination of AlarmManager and BroadcastReceiver on earlier versions.
  3. build.gradle(Module)
    implementation “android.arch.work:work-runtime-ktx:$work_version”
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What are the three main classes used to implement WorkManager?

A

Worker - extend this class and override doWork( )

WorkRequest - Uses Constraints (battery, network) to configure how and when doWork( ) can occur

WorkManager - Works with the OS to schedule the work, honouring specified Constraints

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Give the syntax for extending the ListenableWorker class and implementing the doWork( ) function

A
class MyTaskWorker(appContext: Context, params: WorkerParameters) :
       CoroutineWorker(appContext, params) {
   override suspend fun doWork(): Result {
       try {
           // work to be done goes here
       } catch (e: HttpException) {
           return Result.retry()
       }
       return Result.success()
   }
}

NB Result is the result of a ListenableWorker’s computation. It can be success( ), failure( ) or retry( ).

CoroutineWorker extends ListenableWorker.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What is the difference between the Worker class and the ListenableWorker class?

A

ListenableWorker is the parent class (counterintuitively?)

Worker is recommended, but only for synchronous execution (Worker is destroyed once execution is complete)

Use CoroutineWorker for asynchronous tasks.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

What are the two different implementations of WorkRequest?

A

OneTimeWorkRequest

PeriodicWorkRequest (minimum interval is 15 minutes)

17
Q

Detail the 6 steps to be carried out in the Application class to implement a WorkManager.

A
  1. In overridden Application class…
  2. assign scope variable
  3. launch scope in delayedInt( ) function, setting up application tasks including Worker
  4. Define Constraints with constraintsBuilder( ).build( )
  5. Build WorkRequest
  6. Use WorkManager to enqueue the task

class MyApplication : Application( ) {

private val applicationScope = CoroutineScope(Dispatchers.Default)

override fun onCreate() {
    super.onCreate()
    delayedInit( )
}
    private fun delayedInit( ) {
        applicationScope.launch {
            Timber.plant(Timber.DebugTree( ))
            setupRecurringWork( )
        }
    }
private fun setupRecurringWork() {
    val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.UNMETERED)
            .setRequiresBatteryNotLow(true)
            .setRequiresCharging(true)
            .apply {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    setRequiresDeviceIdle(true)
                }
            }
            .build()

    val repeatingRequest = PeriodicWorkRequestBuilder(1, TimeUnit.DAYS)
            .setConstraints(constraints)
            .build()

    WorkManager.getInstance().enqueueUniquePeriodicWork(
            RefreshDataWorker.WORK_NAME,
            ExistingPeriodicWorkPolicy.KEEP,
            repeatingRequest)
} }
18
Q

Creating on ViewModel to be shared across Fragments requires one thing to be different from normal implementation…

A

At the top of the Fragment class:

private val sharedViewModel: MySharedViewModel by activityViewModels( )