Skip to content

Commit

Permalink
Add Repository solution code
Browse files Browse the repository at this point in the history
  • Loading branch information
OwenScott-GDS committed Mar 22, 2022
1 parent 3b527c7 commit 5dc4c4a
Show file tree
Hide file tree
Showing 45 changed files with 2,055 additions and 0 deletions.
54 changes: 54 additions & 0 deletions RepositoryPattern/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
DevByteRepository - Solution Code
==================================

Solution code for the Repository codelab.

Introduction
------------

DevByteRepository app displays a list of DevByte videos. DevByte videos are
short videos made by the Google Android developer relations team to introduce
new developer features on Android. This app demonstrates the Repository pattern,
the recommended best practice for code separation and architecture. Using
repository pattern the data layer is abstracted from the rest of the app.
Repositories act as mediators between different data sources, such as persistent
models, web services, and caches and the rest of the app.

Pre-requisites
--------------

You need to know:
- How to open, build, and run Android apps with Android Studio.
- The basic Android Architecture Components, ViewModel, and LiveData.
- The data persistence library, Room.
- Building and launching a coroutine.
- Read the logs using the Logcat.
- Binding adapters in data binding.
- Using the Retrofit networking library.


Getting Started
---------------

1. Download and run the app.
2. You need Android Studio 3.4 or higher to build this project.

License
-------

Copyright 2019 Google, Inc.

Licensed to the Apache Software Foundation (ASF) under one or more contributor
license agreements. See the NOTICE file distributed with this work for
additional information regarding copyright ownership. The ASF licenses this
file to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License.
111 changes: 111 additions & 0 deletions RepositoryPattern/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright (C) 2019 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: "androidx.navigation.safeargs"
apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion 32
defaultConfig {
applicationId "com.example.android.devbyteviewer"
minSdkVersion 19
targetSdkVersion 32
versionCode 1
versionName "1.0"
vectorDrawables.useSupportLibrary = true
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

buildFeatures {
dataBinding true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

// support libraries
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.google.android.material:material:1.5.0'

// Android KTX
implementation 'androidx.core:core-ktx:1.7.0'

// constraint layout
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'

// navigation
def nav_version = "1.0.0"
implementation "android.arch.navigation:navigation-fragment-ktx:$nav_version"
implementation "android.arch.navigation:navigation-ui-ktx:$nav_version"

// coroutines for getting off the UI thread
def coroutines = "1.6.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"

// retrofit for networking
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'

// moshi for parsing the JSON format
def moshi_version = "1.13.0"
implementation "com.squareup.moshi:moshi:$moshi_version"
implementation "com.squareup.moshi:moshi-kotlin:$moshi_version"
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"

// joda time library for dealing with time
implementation 'joda-time:joda-time:2.10'

// arch components
// ViewModel and LiveData
def lifecycle_version = "2.4.1"
// implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"

// logging
implementation 'com.jakewharton.timber:timber:4.7.1'

// glide for images
implementation 'com.github.bumptech.glide:glide:4.8.0'
kapt 'com.github.bumptech.glide:compiler:4.7.1'

// Room dependency
def room_version = "2.4.1"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"

}
21 changes: 21 additions & 0 deletions RepositoryPattern/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
43 changes: 43 additions & 0 deletions RepositoryPattern/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2019 Google Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.android.devbyteviewer">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:name=".DevByteApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".ui.DevByteActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2019 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.android.devbyteviewer

import android.app.Application
import timber.log.Timber

/**
* Override application to setup background work via WorkManager
*/
class DevByteApplication : Application() {

/**
* onCreate is called before the first screen is shown to the user.
*
* Use it to setup any background tasks, running expensive setup operations in a background
* thread to avoid delaying app start.
*/
override fun onCreate() {
super.onCreate()
Timber.plant(Timber.DebugTree())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2019 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.android.devbyteviewer.database

import androidx.room.Entity
import androidx.room.PrimaryKey
import com.example.android.devbyteviewer.domain.DevByteVideo


/**
* Database entities go in this file. These are responsible for reading and writing from the
* database.
*/


/**
* DatabaseVideo represents a video entity in the database.
*/
@Entity
data class DatabaseVideo constructor(
@PrimaryKey
val url: String,
val updated: String,
val title: String,
val description: String,
val thumbnail: String)


/**
* Map DatabaseVideos to domain entities
*/
fun List<DatabaseVideo>.asDomainModel(): List<DevByteVideo> {
return map {
DevByteVideo(
url = it.url,
title = it.title,
description = it.description,
updated = it.updated,
thumbnail = it.thumbnail)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2019 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.android.devbyteviewer.database

import android.content.Context
import androidx.lifecycle.LiveData
import androidx.room.*

@Dao
interface VideoDao {
@Query("select * from databasevideo")
fun getVideos(): LiveData<List<DatabaseVideo>>

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll( videos: List<DatabaseVideo>)
}



@Database(entities = [DatabaseVideo::class], version = 1)
abstract class VideosDatabase: RoomDatabase() {
abstract val videoDao: VideoDao
}

private lateinit var INSTANCE: VideosDatabase

fun getDatabase(context: Context): VideosDatabase {
synchronized(VideosDatabase::class.java) {
if (!::INSTANCE.isInitialized) {
INSTANCE = Room.databaseBuilder(context.applicationContext,
VideosDatabase::class.java,
"videos").build()
}
}
return INSTANCE
}
Loading

0 comments on commit 5dc4c4a

Please sign in to comment.