Skip to content
This repository has been archived by the owner on Aug 7, 2024. It is now read-only.

28 lesson homework #40

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'androidx.navigation.safeargs.kotlin'
id 'kotlinx-serialization'
}

android {
Expand Down Expand Up @@ -29,13 +31,44 @@ android {
kotlinOptions {
jvmTarget = '1.8'
}
viewBinding {
enabled = true
}
}

dependencies {
def koin_version= "3.2.0"
// Koin Core features
implementation "io.insert-koin:koin-android:$koin_version"
implementation "io.insert-koin:koin-core:$koin_version"
// Navigation Graph
implementation "io.insert-koin:koin-androidx-navigation:$koin_version"
// Koin Test features
testImplementation "io.insert-koin:koin-test:$koin_version"

implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation "com.squareup.okhttp3:okhttp:4.9.3"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1"

implementation "androidx.navigation:navigation-fragment-ktx:2.4.2"
implementation "androidx.navigation:navigation-ui-ktx:2.4.2"

implementation "androidx.fragment:fragment-ktx:1.4.1"
implementation "androidx.activity:activity-ktx:1.4.0"

implementation "androidx.recyclerview:recyclerview:1.2.1"

implementation "io.coil-kt:coil:2.0.0-rc03"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1"
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'

implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'com.google.android.material:material:1.6.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
Expand Down
8 changes: 7 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,28 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.krottv.tmstemp">

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

<application
android:name=".MyApp"
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/Theme.TmsTemp">
<activity
android:name=".MainActivity"
android:name=".view.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

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

</manifest>
11 changes: 0 additions & 11 deletions app/src/main/java/com/github/krottv/tmstemp/MainActivity.kt

This file was deleted.

39 changes: 39 additions & 0 deletions app/src/main/java/com/github/krottv/tmstemp/MyApp.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.github.krottv.tmstemp

import android.app.Application
import com.github.krottv.tmstemp.data.ITunesRemoteDataSourceRetrofit
import com.github.krottv.tmstemp.data.LibraryRemoteDataSourceRetrofit
import com.github.krottv.tmstemp.data.MusicApi
import com.github.krottv.tmstemp.presentation.AlbumsViewModel
import com.github.krottv.tmstemp.presentation.TracksViewModel
import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.context.startKoin
import org.koin.core.module.Module
import org.koin.core.module.dsl.factoryOf
import org.koin.dsl.module

class MyApp : Application() {

private val itunesModule: Module
get() = module {
factory<MusicApi> { ITunesRemoteDataSourceRetrofit() }
}
private val libraryModule: Module
get() = module {
factory<MusicApi> { LibraryRemoteDataSourceRetrofit() }
}
private val viewModelModule: Module
get() = module {
viewModel { AlbumsViewModel(get()) }
viewModel { TracksViewModel(get()) }
}

override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@MyApp)
modules(libraryModule, itunesModule, viewModelModule)
}
}
}
20 changes: 20 additions & 0 deletions app/src/main/java/com/github/krottv/tmstemp/data/DataSourceFake.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.github.krottv.tmstemp.data

import com.github.krottv.tmstemp.domain.AlbumModel

class DataSourceFake {

fun getITunesAlbums(): List<AlbumModel>{
val model = AlbumModel(0,
"https://inspiry-2ee60.web.app/music/images/itunes/hip_hop.jpg",
"Some Text",
10)

val mutableListOf = ArrayList<AlbumModel>(10)
for (i in 0..10){
mutableListOf.add(model.copy(name = "Some Text $i"))
}

return mutableListOf
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.github.krottv.tmstemp.data

import android.util.Log
import com.github.krottv.tmstemp.domain.AlbumModel
import com.github.krottv.tmstemp.domain.Tracks
import com.github.krottv.tmstemp.domain.TracksModel
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import retrofit2.Retrofit
import retrofit2.create

class ITunesRemoteDataSourceRetrofit : MusicApi {

override suspend fun getAlbums(): List<AlbumModel> {
val retrofit = Retrofit.Builder()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Плохой паттерн.

  1. Ретрофит это тяжёлый объект, каждый раз при вызове метода его создавать неправильно.
  2. "https://us-central1-inspiry-2ee60.cloudfunctions.net/" - это baseUrl. "getItunesAlbums" - это путь. Прописывается в MusicApi.

.baseUrl("https://us-central1-inspiry-2ee60.cloudfunctions.net/getItunesAlbums/")
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.build()

val musicApi: MusicApi = retrofit.create()
return musicApi.getAlbums()
}

override suspend fun getTracks(albumId: Long): TracksModel {
val retrofit = Retrofit.Builder()
.baseUrl("https://us-central1-inspiry-2ee60.cloudfunctions.net/getItunesTracks/")
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.build()

val musicApi: MusicApi = retrofit.create()

return musicApi.getTracks(1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.github.krottv.tmstemp.data

import com.github.krottv.tmstemp.domain.AlbumModel
import com.github.krottv.tmstemp.domain.TracksModel
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import retrofit2.Retrofit
import retrofit2.create

class LibraryRemoteDataSourceRetrofit : MusicApi {

override suspend fun getAlbums(): List<AlbumModel> {
val retrofit = Retrofit.Builder()
.baseUrl("https://us-central1-inspiry-2ee60.cloudfunctions.net/getLibraryAlbums/")
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.build()

val musicApi: MusicApi = retrofit.create()

return musicApi.getAlbums()
}

override suspend fun getTracks(albumId: Long): TracksModel {
val retrofit = Retrofit.Builder()
.baseUrl("https://us-central1-inspiry-2ee60.cloudfunctions.net/getLibraryTracks/")
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.build()

val musicApi: MusicApi = retrofit.create()

return musicApi.getTracks(1)
}
}
14 changes: 14 additions & 0 deletions app/src/main/java/com/github/krottv/tmstemp/data/MusicApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.github.krottv.tmstemp.data

import com.github.krottv.tmstemp.domain.AlbumModel
import com.github.krottv.tmstemp.domain.TracksModel
import retrofit2.http.GET
import retrofit2.http.Query

interface MusicApi {
@GET("getAlbums")
suspend fun getAlbums(): List<AlbumModel>

@GET("getTrack")
suspend fun getTracks(@Query("albumId") albumId: Long): TracksModel
}
11 changes: 11 additions & 0 deletions app/src/main/java/com/github/krottv/tmstemp/domain/Album.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.github.krottv.tmstemp.domain

import kotlinx.serialization.Serializable

@Serializable
data class Album(
var id: Int,
var image: String,
var name: String,
var trackCount: Int
)
13 changes: 13 additions & 0 deletions app/src/main/java/com/github/krottv/tmstemp/domain/AlbumModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.github.krottv.tmstemp.domain

import android.media.Image
import kotlinx.serialization.Serializable

@Serializable
data class AlbumModel(
val id: Long,
val image: String,
val name: String,
val trackCount: Int) {

}
11 changes: 11 additions & 0 deletions app/src/main/java/com/github/krottv/tmstemp/domain/Tracks.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.github.krottv.tmstemp.domain

import kotlinx.serialization.Serializable

@Serializable
data class Tracks(
var artist: String,
var image: String,
var title: String,
var url: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.github.krottv.tmstemp.domain

import kotlinx.serialization.Serializable

@Serializable
data class TracksModel(
var album: Album ,
var tracks: ArrayList<Tracks>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.github.krottv.tmstemp.presentation

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.github.krottv.tmstemp.data.ITunesRemoteDataSourceRetrofit
import com.github.krottv.tmstemp.data.MusicApi
import com.github.krottv.tmstemp.domain.AlbumModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class AlbumsViewModel(val musicApi: MusicApi): ViewModel(){

private val _stateITunes = MutableStateFlow<List<AlbumModel>?>(null)
val stateITunes: StateFlow<List<AlbumModel>?> = _stateITunes

fun loadData() {
viewModelScope.launch(Dispatchers.IO) {
_stateITunes.emit(musicApi.getAlbums())
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.github.krottv.tmstemp.presentation

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.github.krottv.tmstemp.data.ITunesRemoteDataSourceRetrofit
import com.github.krottv.tmstemp.data.MusicApi
import com.github.krottv.tmstemp.domain.AlbumModel
import com.github.krottv.tmstemp.domain.Tracks
import com.github.krottv.tmstemp.domain.TracksModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class TracksViewModel(val musicApi: MusicApi): ViewModel() {
private val _stateITunes = MutableStateFlow<TracksModel?>(null)
val stateITunes: StateFlow<TracksModel?> = _stateITunes

fun loadTracks() {
viewModelScope.launch(Dispatchers.IO) {
_stateITunes.emit(musicApi.getTracks(1))
}
}
}
46 changes: 46 additions & 0 deletions app/src/main/java/com/github/krottv/tmstemp/view/AlbumsAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.github.krottv.tmstemp.view

import android.graphics.Outline
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewOutlineProvider
import androidx.recyclerview.widget.RecyclerView
import coil.load
import com.github.krottv.tmstemp.R
import com.github.krottv.tmstemp.domain.AlbumModel
import com.github.krottv.tmstemp.domain.Tracks

class AlbumsAdapter(data: List<AlbumModel>): RecyclerView.Adapter<AlbumsViewHolder>() {

var data: List<AlbumModel> = data
set(value) {
field = value
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AlbumsViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_album, parent, false)

return AlbumsViewHolder(view)
}

override fun onBindViewHolder(holder: AlbumsViewHolder, position: Int) {
val item = data[position]
holder.imageAlbum.load(item.image)
holder.textAlbum.text = item.name

holder.imageAlbum.clipToOutline = true
holder.imageAlbum.outlineProvider = object: ViewOutlineProvider() {
override fun getOutline(p0: View, p1: Outline) {
p1.setRoundRect(0, 0, p0.width, p0.height, 10.0F)
}
}
}

override fun getItemCount(): Int {
return data.size
}


}
Loading