Have a burning question? Leave it in the comments below for a chance to get it answered by the Android team. 👇👇🏻👇🏿👇🏽 👇🏾👇🏼
@SachaHindu88 Жыл бұрын
Do we have any video on UI layer and domain layer like this...
@ivasuktelesuk100 Жыл бұрын
Lets say we have also Groups. Each Task assigned to one or more groups. It could be separate table task_id | group_id. Now we need display at one screen all tasks with info about all their groups. So we need to receive list of tasks, list of groups and list of task-groups relations. How our Data layer should looks like? Do we need introduce Domsin layer(UseCase) here?
@donturner1928 Жыл бұрын
In this case, I'd suggest updating the Task model to include a List, then update your SQL query inside TaskDao to perform a join on your Groups table to return the groups which each Task is associated with. I wouldn't introduce the domain layer (UseCase) for this simple addition, however, if you have significant business logic for filtering and/or sorting those tasks then it may be worth introducing one or more UseCases to contain that logic. In the Now in Android app, we have a similar one-to-many relationship where NewsResources can have up to 5 Topics. In this case, we introduced a TopicsRepository because we have a screen which displays all the Topics independently of the NewsResources which are associated with them github.com/android/nowinandroid/blob/d20910595522867067e7a7d1c542e95fc5f5155d/core/data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/TopicsRepository.kt#L23.
@sherby90 Жыл бұрын
in the repository -> createTask, why do you create a Task first, then convert to LocalTask? Why not LocalTask directly?
@donturner1928 Жыл бұрын
The Task model encapsulates the logic of creating a task (e.g. with isCompleted = false default value). If you were to create LocalTask directly then you would bypass that logic. To be fair, this isn't ideal since you _always_ need to create a Task before you can create a LocalTask so it would probably be better to encapsulate this creation logic inside a separate function inside LocalTask e.g. newLocalTask which includes those defaults.
@zachyang104111 ай бұрын
Can anyone help me understand at 16:22, why observeAll() is not a suspend function? Is that because it returns a flow? Can this function to be suspend?
@517Amit Жыл бұрын
Nice code lab.
@holatechm Жыл бұрын
Great!! tutorial
@HassanBadran-w4o Жыл бұрын
How do you handle API Failures? how do you notify the tasks observers that our api failed?
@GG9K71 Жыл бұрын
About the refresh() method, fetching remote data, and deleting the local one could be done parallel, in two separate coroutines.
@donturner1928 Жыл бұрын
The `refresh` method could be implemented in a number of ways, however, your proposed way is even more risky than the one implemented here, namely because the remote job could fail whilst the local data is deleted, leaving your user with no data at all. For any production app, I'd suggest following the guidance here: developer.android.com/topic/architecture/data-layer/offline-first
@GG9K71 Жыл бұрын
@@donturner1928 You are right about that, I was thinking about performance only.
@lalobarrios16 Жыл бұрын
While the refresh method is not the main point about this video, it is important to know that in production apps this refresh method needs to run a transaction in room to avoid race conditions, specially if run in viewModelScope which detaches according to its lifecycle. This type of conflict can be categorized as WAW (write after write) if we consider that the first delete is a write. The actual description of this conflict happens if exactly after we delete all locals tasks we detach from viewModelScope so we missed the insertion and then we no longer have local tasks. The right mitigation would be to run a @Transaction in room.
@ugommirikwe Жыл бұрын
Here: 15:12 I’m thinking the functions to map local to domain/repository data types should belong in the repository/domain, so instead of implementing the `LocalTask.toExternal` extension function rather do it with the `DefaultTaskRepository().observeAll()` function: ``` … return localDataSource.observeAll().map { Task(it…) } ``` No? 🤔
@donturner1928 Жыл бұрын
By abstracting the mapping logic into its own function you guarantee that any changes to `Task`, `LocalTask` or the mapping logic can be done in a single place. It also makes this logic easier to test than if it's hidden inside a repository function.
@douglaskazumi Жыл бұрын
@@donturner1928why are they extension functions and not actual members of LocalTask?
@hmsmurtaza Жыл бұрын
Please enable Dark Mode in your codelabs, difficult to read on white screens
@박종민-n1y Жыл бұрын
Thank you for the good content. The code font is very pretty. May I know the name of the font?
@donturner1928 Жыл бұрын
Google Sans Mono. It's a proprietary font.
@saeednoshadi3922 Жыл бұрын
Is there any video to test retrofit network data?
@donturner1928 Жыл бұрын
You'd usually do this in manual QA testing to avoid making your automated tests slow and/or flaky
@saeednoshadi3922 Жыл бұрын
@@donturner1928 You mean we shouldn't write any test and mock for network?
@donturner1928 Жыл бұрын
@@saeednoshadi3922 I mean you should use a fake network class when testing subjects which rely on the network.
@bubnov_a_a Жыл бұрын
Please pay attention to the screen recording settings or the final video rendering settings. There are annoying video encoding artefacts when showing the studio. You could work on colour scheme entire video also(tone and brightness). Many of us work all with screens and our eyes become too sensitive.
@eriknyk2k Жыл бұрын
Thanks for the video, is there a repository with the code shown in the video? Regards.
@donturner1928 Жыл бұрын
It's in the video description but here you go: github.com/android/architecture-samples
@hk4545581 Жыл бұрын
can your team reset Write WebRtc for android document?
@sheikhchilli7560 Жыл бұрын
Why didnt we use taskrepository interface which is usefull for creating fake repository? Also used for decoupling. Is there any reason?
@c_uludag Жыл бұрын
Totally unrelated questions. What is the new font that Google is using in their slides? And in this tutorial that shown in Android Studio?😃 Looks nice and clean.
@donturner1928 Жыл бұрын
Google Sans Mono. It's a proprietary font.
@withKaaveh Жыл бұрын
Please use dark mode for the presentation slides
@kleeenco10 ай бұрын
google doesn't understand what the repository pattern is
@ka61er Жыл бұрын
Anyone get turn off syntax high light when access file has @Dao like me :((
@ivasuktelesuk100 Жыл бұрын
@Android Developers How to pass errors/exceptions from Data layer to UI?
@GakisStylianos Жыл бұрын
Return a result type?
@donturner1928 Жыл бұрын
In the UI, when you collect from the flow use `catch` to catch any exceptions. Throwing/handling exceptions is preferable to using a Result wrapper because it avoids the overhead of wrapping and unwrapping the actual result.
@GakisStylianos Жыл бұрын
@@donturner1928 I really wouldn't recommend returning exceptions, especially for known errors from your data layer 🤔 How much do you want to stand behind this suggestion here? Does Now In Android do the same at any part of the code base so we could take a look to see what you mean?
@GakisStylianos Жыл бұрын
Plus then you got the situation where the exception isn't specified anywhere, and you can very well forget to catch bringing issues to your project. A return type forces you to handle it, since you never want to ignore it in the first place. I don't know, I could be wrong here but I can't imagine myself preferring that approach.
@donturner1928 Жыл бұрын
Yeah, that's a really good point, thanks. My initial answer wasn't comprehensive. I should have added that Result is a preferable choice in situations where you want to force the UI to handle known errors, and this is indeed what we do in Now in Android. In fact, we convert any exceptions in a flow into a Result.Error type which contains the exception: github.com/android/nowinandroid/blob/d20910595522867067e7a7d1c542e95fc5f5155d/core/common/src/main/java/com/google/samples/apps/nowinandroid/core/result/Result.kt#L24