How to build a data layer

Поделиться
HTML-код
  • Опубликовано: 20 авг 2024
  • In this workshop, you'll learn about the data layer and how it fits into your overall app architecture. Build the data layer for a TODO app which creates, stores, and updates tasks. Explore repositories, data sources, and data models. Last, discover how to expose data using streams, and how to test that your data layer is behaving as it should.
    Resources:
    Build an offline-first app → goo.gle/offlin...
    About the data layer → goo.gle/androi...
    Build a Data Layer Codelab → goo.gle/androi...
    Speaker: Don Turner
    Watch more:
    Watch all Android and Play Sessions → goo.gle/IO23_a...
    Watch all the workshops from Google I/O 2023 → goo.gle/IO23_w...
    Watch more Mobile Sessions → goo.gle/IO23_m...
    All Google I/O 2023 Sessions → goo.gle/IO23_all
    Subscribe to Android Developers → goo.gle/Androi...
    #GoogleIO #Featured #AndroidDevelopers #tools

Комментарии • 43

  • @AndroidDevelopers
    @AndroidDevelopers  Год назад +12

    Have a burning question? Leave it in the comments below for a chance to get it answered by the Android team. 👇👇🏻👇🏿👇🏽 👇🏾👇🏼

    • @SachaHindu88
      @SachaHindu88 Год назад +4

      Do we have any video on UI layer and domain layer like this...

  • @hmsmurtaza
    @hmsmurtaza Год назад +3

    Please enable Dark Mode in your codelabs, difficult to read on white screens

  • @bubnov_a_a
    @bubnov_a_a Год назад +1

    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.

  • @holatechm
    @holatechm 10 месяцев назад

    Great!! tutorial

  • @ivasuktelesuk100
    @ivasuktelesuk100 Год назад +2

    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
      @donturner1928 Год назад +4

      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.

  • @zachyang1041
    @zachyang1041 7 месяцев назад

    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
    @517Amit Год назад

    Nice code lab.

  • @sherby90
    @sherby90 Год назад +1

    in the repository -> createTask, why do you create a Task first, then convert to LocalTask? Why not LocalTask directly?

    • @donturner1928
      @donturner1928 Год назад +2

      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.

  • @GN9K71
    @GN9K71 Год назад

    About the refresh() method, fetching remote data, and deleting the local one could be done parallel, in two separate coroutines.

    • @donturner1928
      @donturner1928 Год назад +3

      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

    • @GN9K71
      @GN9K71 Год назад +1

      @@donturner1928 You are right about that, I was thinking about performance only.

    • @lalobarrios16
      @lalobarrios16 11 месяцев назад +1

      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.

  • @user-cg5tv1mp4y
    @user-cg5tv1mp4y Год назад +1

    Thank you for the good content. The code font is very pretty. May I know the name of the font?

    • @donturner1928
      @donturner1928 Год назад

      Google Sans Mono. It's a proprietary font.

  • @kleeenco
    @kleeenco 6 месяцев назад

    google doesn't understand what the repository pattern is

  • @user-ew8wc2mc1o
    @user-ew8wc2mc1o 10 месяцев назад

    How do you handle API Failures? how do you notify the tasks observers that our api failed?

    • @justmeagain9302
      @justmeagain9302 2 месяца назад

      That's the neat part... It doesn't fail. No more code to worry abou👓🤏

  • @sheikhchilli7560
    @sheikhchilli7560 Год назад

    Why didnt we use taskrepository interface which is usefull for creating fake repository? Also used for decoupling. Is there any reason?

  • @hk4545581
    @hk4545581 Год назад

    can your team reset Write WebRtc for android document?

  • @eriknyk2k
    @eriknyk2k Год назад

    Thanks for the video, is there a repository with the code shown in the video? Regards.

    • @donturner1928
      @donturner1928 Год назад

      It's in the video description but here you go: github.com/android/architecture-samples

  • @ka61er
    @ka61er Год назад

    Anyone get turn off syntax high light when access file has @Dao like me :((

  • @canuludag4332
    @canuludag4332 Год назад

    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
      @donturner1928 Год назад +1

      Google Sans Mono. It's a proprietary font.

  • @withKaaveh
    @withKaaveh Год назад +1

    Please use dark mode for the presentation slides

  • @saeednoshadi3922
    @saeednoshadi3922 Год назад

    Is there any video to test retrofit network data?

    • @donturner1928
      @donturner1928 Год назад +1

      You'd usually do this in manual QA testing to avoid making your automated tests slow and/or flaky

    • @saeednoshadi3922
      @saeednoshadi3922 Год назад

      @@donturner1928 You mean we shouldn't write any test and mock for network?

    • @donturner1928
      @donturner1928 Год назад +1

      @@saeednoshadi3922 I mean you should use a fake network class when testing subjects which rely on the network.

  • @ugommirikwe
    @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
      @donturner1928 Год назад +1

      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
      @douglaskazumi 8 месяцев назад

      ​@@donturner1928why are they extension functions and not actual members of LocalTask?

  • @isThomas
    @isThomas Год назад

    Video is flickering too much...😵‍💫😵‍💫😵‍💫

  • @ivasuktelesuk100
    @ivasuktelesuk100 Год назад +1

    @Android Developers How to pass errors/exceptions from Data layer to UI?

    • @GakisStylianos
      @GakisStylianos Год назад

      Return a result type?

    • @donturner1928
      @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
      @GakisStylianos Год назад +1

      @@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
      @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
      @donturner1928 Год назад +1

      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