From 25bdd509a3bb29503c04bc5e3a7242f268cbd8d4 Mon Sep 17 00:00:00 2001 From: WentuM Date: Mon, 1 Mar 2021 22:37:10 +0300 Subject: [PATCH 1/2] task/hw10_weather_application_continue --- app/build.gradle | 22 ++- app/src/main/AndroidManifest.xml | 5 +- .../example/androidpractice2020/data/City.kt | 34 ++++ .../data/WeatherApplication.kt | 15 ++ .../androidpractice2020/data/WeatherDao.kt | 31 ++++ .../data/WeatherRepositoryImpl.kt | 97 ++++++++++ .../data/WeatherRoomDatabase.kt | 30 ++++ .../{factory => data/api}/ApiFactory.kt | 6 +- .../api}/LoggingInterceptor.kt | 2 +- .../{factory => data/api}/WeatherApi.kt | 4 +- .../api/response}/CitiesWeatherResponse.kt | 6 +- .../api/response}/WeatherResponse.kt | 2 +- .../domain/FindCityUseCase.kt | 41 +++++ .../domain/WeatherRepository.kt | 24 +++ .../DetailCityActivity.kt | 23 ++- .../presentation/MainActivity.kt | 165 ++++++++++++++++++ .../recyclerview/CityAdapter.kt | 7 +- .../recyclerview/CityHolder.kt | 10 +- .../androidpractice2020/recyclerview/City.kt | 7 - .../androidpractice2020/ui/MainActivity.kt | 131 -------------- app/src/main/res/layout/activity_main.xml | 2 +- build.gradle | 2 +- 22 files changed, 497 insertions(+), 169 deletions(-) create mode 100644 app/src/main/java/com/example/androidpractice2020/data/City.kt create mode 100644 app/src/main/java/com/example/androidpractice2020/data/WeatherApplication.kt create mode 100644 app/src/main/java/com/example/androidpractice2020/data/WeatherDao.kt create mode 100644 app/src/main/java/com/example/androidpractice2020/data/WeatherRepositoryImpl.kt create mode 100644 app/src/main/java/com/example/androidpractice2020/data/WeatherRoomDatabase.kt rename app/src/main/java/com/example/androidpractice2020/{factory => data/api}/ApiFactory.kt (92%) rename app/src/main/java/com/example/androidpractice2020/{factory => data/api}/LoggingInterceptor.kt (92%) rename app/src/main/java/com/example/androidpractice2020/{factory => data/api}/WeatherApi.kt (72%) rename app/src/main/java/com/example/androidpractice2020/{factory => data/api/response}/CitiesWeatherResponse.kt (71%) rename app/src/main/java/com/example/androidpractice2020/{factory => data/api/response}/WeatherResponse.kt (93%) create mode 100644 app/src/main/java/com/example/androidpractice2020/domain/FindCityUseCase.kt create mode 100644 app/src/main/java/com/example/androidpractice2020/domain/WeatherRepository.kt rename app/src/main/java/com/example/androidpractice2020/{ui => presentation}/DetailCityActivity.kt (69%) create mode 100644 app/src/main/java/com/example/androidpractice2020/presentation/MainActivity.kt rename app/src/main/java/com/example/androidpractice2020/{ => presentation}/recyclerview/CityAdapter.kt (64%) rename app/src/main/java/com/example/androidpractice2020/{ => presentation}/recyclerview/CityHolder.kt (84%) delete mode 100644 app/src/main/java/com/example/androidpractice2020/recyclerview/City.kt delete mode 100644 app/src/main/java/com/example/androidpractice2020/ui/MainActivity.kt diff --git a/app/build.gradle b/app/build.gradle index 249ef86..09f4b30 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,14 +12,21 @@ android { targetSdkVersion 30 versionCode 1 versionName "1.0" + apply plugin: 'kotlin-kapt' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + + androidExtensions { experimental = true } + buildFeatures { + viewBinding true + } + buildTypes { release { minifyEnabled false @@ -55,6 +62,18 @@ dependencies { + def room_version = "2.2.6" + + implementation "androidx.room:room-runtime:$room_version" + kapt "androidx.room:room-compiler:$room_version" + + // optional - Kotlin Extensions and Coroutines support for Room + implementation "androidx.room:room-ktx:$room_version" + + // optional - Test helpers + testImplementation "androidx.room:room-testing:$room_version" + + // region Retrofit implementation "com.squareup.retrofit2:retrofit:${retrofit}" implementation "com.squareup.retrofit2:converter-gson:${retrofit}" @@ -76,7 +95,4 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - - - } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 211274c..8da3378 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,13 +7,14 @@ - + @@ -21,7 +22,7 @@ - + \ No newline at end of file diff --git a/app/src/main/java/com/example/androidpractice2020/data/City.kt b/app/src/main/java/com/example/androidpractice2020/data/City.kt new file mode 100644 index 0000000..49c6e81 --- /dev/null +++ b/app/src/main/java/com/example/androidpractice2020/data/City.kt @@ -0,0 +1,34 @@ +package com.example.androidpractice2020.data + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.example.androidpractice2020.data.api.response.InfoCity +import kotlinx.coroutines.withContext + +@Entity(tableName = "city") +data class City( + @PrimaryKey + @ColumnInfo(name = "id") + var id: Int, + @ColumnInfo(name = "name") + var name: String, + @ColumnInfo(name = "temperature") + var temp: Double, + @ColumnInfo(name = "description") + var description: String, + @ColumnInfo(name = "numb_humidity") + var numbHumidity: Int, + @ColumnInfo(name = "deg") + var deg: Int +) { + companion object { + fun mapResponsetoEntity(infoCity: InfoCity): City { + with(infoCity) { + return City( + id, name, main.temp, weather[0].description, main.humidity, wind.deg + ) + } + } + } +} diff --git a/app/src/main/java/com/example/androidpractice2020/data/WeatherApplication.kt b/app/src/main/java/com/example/androidpractice2020/data/WeatherApplication.kt new file mode 100644 index 0000000..da37961 --- /dev/null +++ b/app/src/main/java/com/example/androidpractice2020/data/WeatherApplication.kt @@ -0,0 +1,15 @@ +package com.example.androidpractice2020.data + +import android.app.Application +import com.example.androidpractice2020.data.api.ApiFactory + +class WeatherApplication : Application() { + + val database by lazy { + WeatherRoomDatabase.getDataBase(this) + } + + val repository by lazy { + WeatherRepositoryImpl(ApiFactory.weatherApi ,database.weatherDao()) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidpractice2020/data/WeatherDao.kt b/app/src/main/java/com/example/androidpractice2020/data/WeatherDao.kt new file mode 100644 index 0000000..1ec8508 --- /dev/null +++ b/app/src/main/java/com/example/androidpractice2020/data/WeatherDao.kt @@ -0,0 +1,31 @@ +package com.example.androidpractice2020.data + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query + +@Dao +interface WeatherDao { + + + suspend fun insert(list: List) { + insrt(*list.toTypedArray()) + } + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insrt(vararg list: City) + + @Query("SELECT * FROM city") + suspend fun getAllCities(): List + + @Query("SELECT * FROM city WHERE id = :idCity") + suspend fun getCityById(idCity: Int): City + + @Query("SELECT * FROM city WHERE name = :nameCity") + suspend fun getCityByName(nameCity: String): City + + @Query("DELETE FROM city") + suspend fun deleteAllCity() + +} diff --git a/app/src/main/java/com/example/androidpractice2020/data/WeatherRepositoryImpl.kt b/app/src/main/java/com/example/androidpractice2020/data/WeatherRepositoryImpl.kt new file mode 100644 index 0000000..3dc8f51 --- /dev/null +++ b/app/src/main/java/com/example/androidpractice2020/data/WeatherRepositoryImpl.kt @@ -0,0 +1,97 @@ +package com.example.androidpractice2020.data + +import com.example.androidpractice2020.data.api.WeatherApi +import com.example.androidpractice2020.domain.WeatherRepository +import java.lang.Exception +import java.net.UnknownHostException + +class WeatherRepositoryImpl( + private val weatherApi: WeatherApi, + private val weatherDao: WeatherDao +) : WeatherRepository { + + + override suspend fun getWeatherByName(cityName: String) = + try { + val weatherResponse = weatherApi.getWeather(cityName) + City( + weatherResponse.id, + weatherResponse.name, + weatherResponse.main.temp, + weatherResponse.weather[0].description, + weatherResponse.main.humidity, + weatherResponse.wind.deg + ) + + } catch (e: Exception) { + when (e) { + is UnknownHostException -> weatherDao.getCityByName(cityName) + else -> City( + -1, + "", + -1.0, + "", + -1, + 1 + ) + } + } + + override suspend fun getCityById(cityId: Int): City = + try { + val weatherResponse = weatherApi.getCityById(cityId) + City( + weatherResponse.id, + weatherResponse.name, + weatherResponse.main.temp, + weatherResponse.weather[0].description, + weatherResponse.main.humidity, + weatherResponse.wind.deg + ) + } catch (e: UnknownHostException) { + weatherDao.getCityById(cityId) + } + + override suspend fun getCitiesWeather( + latitudeUser: Double, + longitude: Double, + countCities: Int + ): ArrayList { + var result: ArrayList = arrayListOf() + try { + var weatherResponse = + weatherApi.getCitiesWeather(latitudeUser, longitude, countCities).list + var i = 0 + while (i < weatherResponse.size) { + result.add(City.mapResponsetoEntity(weatherResponse[i])) + i++ + } + weatherDao.deleteAllCity() + weatherDao.insert(result) + } catch (e: UnknownHostException) { + result = weatherDao.getAllCities() as ArrayList + } + return result + } + +// @SuppressLint("MissingPermission") +// override suspend fun getGeoPositionUser( +// applicationContext: Context, +// boolean: Boolean +// ): DoubleArray { +// var fusedLocationProviderClient = +// LocationServices.getFusedLocationProviderClient(applicationContext) +// var longitude = 37.6156 +// var latitude = 55.7522 +// fusedLocationProviderClient.lastLocation.addOnCompleteListener { task -> +// var location: Location? = task.result +// if (location != null) { +// longitude = location.longitude +// latitude = location.latitude +// Log.e("qweqw", "$latitude") +// Log.e("qweqwe", "$longitude") +// } +// } +// return doubleArrayOf(latitude, longitude) +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidpractice2020/data/WeatherRoomDatabase.kt b/app/src/main/java/com/example/androidpractice2020/data/WeatherRoomDatabase.kt new file mode 100644 index 0000000..7a72cdd --- /dev/null +++ b/app/src/main/java/com/example/androidpractice2020/data/WeatherRoomDatabase.kt @@ -0,0 +1,30 @@ +package com.example.androidpractice2020.data + +import android.content.Context +import androidx.room.* + +@Database(entities = arrayOf(City::class), version = 2, exportSchema = false) +abstract class WeatherRoomDatabase : RoomDatabase() { + + abstract fun weatherDao(): WeatherDao + + companion object { + + @Volatile + private var INSTANCE: WeatherRoomDatabase? = null + + fun getDataBase(context: Context): WeatherRoomDatabase { + return INSTANCE ?: synchronized(this) { + val instance = Room.databaseBuilder( + context.applicationContext, + WeatherRoomDatabase::class.java, + "city_database" + ).fallbackToDestructiveMigration() + .build() + INSTANCE = instance + + instance + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidpractice2020/factory/ApiFactory.kt b/app/src/main/java/com/example/androidpractice2020/data/api/ApiFactory.kt similarity index 92% rename from app/src/main/java/com/example/androidpractice2020/factory/ApiFactory.kt rename to app/src/main/java/com/example/androidpractice2020/data/api/ApiFactory.kt index 017cf9e..94e425f 100644 --- a/app/src/main/java/com/example/androidpractice2020/factory/ApiFactory.kt +++ b/app/src/main/java/com/example/androidpractice2020/data/api/ApiFactory.kt @@ -1,4 +1,4 @@ -package com.example.androidpractice2020.factory +package com.example.androidpractice2020.data.api import com.example.androidpractice2020.BuildConfig import okhttp3.Interceptor @@ -53,7 +53,9 @@ object ApiFactory { } val weatherApi by lazy { - retrofit.create(WeatherApi::class.java) + retrofit.create( + WeatherApi::class.java + ) } diff --git a/app/src/main/java/com/example/androidpractice2020/factory/LoggingInterceptor.kt b/app/src/main/java/com/example/androidpractice2020/data/api/LoggingInterceptor.kt similarity index 92% rename from app/src/main/java/com/example/androidpractice2020/factory/LoggingInterceptor.kt rename to app/src/main/java/com/example/androidpractice2020/data/api/LoggingInterceptor.kt index 632a86e..08b47ac 100644 --- a/app/src/main/java/com/example/androidpractice2020/factory/LoggingInterceptor.kt +++ b/app/src/main/java/com/example/androidpractice2020/data/api/LoggingInterceptor.kt @@ -1,4 +1,4 @@ -package com.example.androidpractice2020.factory +package com.example.androidpractice2020.data.api import com.example.androidpractice2020.BuildConfig import okhttp3.logging.HttpLoggingInterceptor diff --git a/app/src/main/java/com/example/androidpractice2020/factory/WeatherApi.kt b/app/src/main/java/com/example/androidpractice2020/data/api/WeatherApi.kt similarity index 72% rename from app/src/main/java/com/example/androidpractice2020/factory/WeatherApi.kt rename to app/src/main/java/com/example/androidpractice2020/data/api/WeatherApi.kt index e287089..4c54137 100644 --- a/app/src/main/java/com/example/androidpractice2020/factory/WeatherApi.kt +++ b/app/src/main/java/com/example/androidpractice2020/data/api/WeatherApi.kt @@ -1,5 +1,7 @@ -package com.example.androidpractice2020.factory +package com.example.androidpractice2020.data.api +import com.example.androidpractice2020.data.api.response.CitiesWeatherResponse +import com.example.androidpractice2020.data.api.response.WeatherResponse import retrofit2.http.GET import retrofit2.http.Query diff --git a/app/src/main/java/com/example/androidpractice2020/factory/CitiesWeatherResponse.kt b/app/src/main/java/com/example/androidpractice2020/data/api/response/CitiesWeatherResponse.kt similarity index 71% rename from app/src/main/java/com/example/androidpractice2020/factory/CitiesWeatherResponse.kt rename to app/src/main/java/com/example/androidpractice2020/data/api/response/CitiesWeatherResponse.kt index dda31e3..3e50e13 100644 --- a/app/src/main/java/com/example/androidpractice2020/factory/CitiesWeatherResponse.kt +++ b/app/src/main/java/com/example/androidpractice2020/data/api/response/CitiesWeatherResponse.kt @@ -1,9 +1,11 @@ -package com.example.androidpractice2020.factory +package com.example.androidpractice2020.data.api.response + +import com.example.androidpractice2020.data.City data class CitiesWeatherResponse( val cod: String, val count: Int, - val list: List, + val list: ArrayList, val message: String ) diff --git a/app/src/main/java/com/example/androidpractice2020/factory/WeatherResponse.kt b/app/src/main/java/com/example/androidpractice2020/data/api/response/WeatherResponse.kt similarity index 93% rename from app/src/main/java/com/example/androidpractice2020/factory/WeatherResponse.kt rename to app/src/main/java/com/example/androidpractice2020/data/api/response/WeatherResponse.kt index 4fd8fe9..aa963ad 100644 --- a/app/src/main/java/com/example/androidpractice2020/factory/WeatherResponse.kt +++ b/app/src/main/java/com/example/androidpractice2020/data/api/response/WeatherResponse.kt @@ -1,4 +1,4 @@ -package com.example.androidpractice2020.factory +package com.example.androidpractice2020.data.api.response data class WeatherResponse( diff --git a/app/src/main/java/com/example/androidpractice2020/domain/FindCityUseCase.kt b/app/src/main/java/com/example/androidpractice2020/domain/FindCityUseCase.kt new file mode 100644 index 0000000..2588013 --- /dev/null +++ b/app/src/main/java/com/example/androidpractice2020/domain/FindCityUseCase.kt @@ -0,0 +1,41 @@ +package com.example.androidpractice2020.domain + +import android.content.Context +import com.example.androidpractice2020.data.City +import com.example.androidpractice2020.data.WeatherRepositoryImpl +import com.example.androidpractice2020.data.api.response.CitiesWeatherResponse +import com.example.androidpractice2020.data.api.response.WeatherResponse +import kotlinx.coroutines.withContext +import kotlin.coroutines.CoroutineContext + +class FindCityUseCase( + private val weatherRepositoryImpl: WeatherRepositoryImpl, + private val context: CoroutineContext +) { + + suspend fun findWeatherCityByName(cityName: String): City = + withContext(context) { + weatherRepositoryImpl.getWeatherByName(cityName) + } + + suspend fun findWeatherCityById(cityId: Int): City = + withContext(context) { + weatherRepositoryImpl.getCityById(cityId) + } + + suspend fun findWeatherCitiesByCoordinates( + latitudeUser: Double, + longitudeUser: Double, + countCities: Int + ): ArrayList = + withContext(context) { + weatherRepositoryImpl.getCitiesWeather(latitudeUser, longitudeUser, countCities) + } + +// suspend fun getCoordinatesByUser( +// applicationContext: Context, boolean: Boolean +// ): DoubleArray = +// withContext(context) { +// weatherRepositoryImpl.getGeoPositionUser(applicationContext, boolean) +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidpractice2020/domain/WeatherRepository.kt b/app/src/main/java/com/example/androidpractice2020/domain/WeatherRepository.kt new file mode 100644 index 0000000..c7eac26 --- /dev/null +++ b/app/src/main/java/com/example/androidpractice2020/domain/WeatherRepository.kt @@ -0,0 +1,24 @@ +package com.example.androidpractice2020.domain + +import com.example.androidpractice2020.data.City + +interface WeatherRepository { + + suspend fun getWeatherByName( + cityName: String + ): City + + suspend fun getCityById( + cityId: Int + ): City + + suspend fun getCitiesWeather( + latitudeUser: Double, + longitude: Double, + countCities: Int + ): ArrayList + +// suspend fun getGeoPositionUser( +// applicationContext: Context, boolean: Boolean +// ): DoubleArray +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidpractice2020/ui/DetailCityActivity.kt b/app/src/main/java/com/example/androidpractice2020/presentation/DetailCityActivity.kt similarity index 69% rename from app/src/main/java/com/example/androidpractice2020/ui/DetailCityActivity.kt rename to app/src/main/java/com/example/androidpractice2020/presentation/DetailCityActivity.kt index a70c948..2ff1bcb 100644 --- a/app/src/main/java/com/example/androidpractice2020/ui/DetailCityActivity.kt +++ b/app/src/main/java/com/example/androidpractice2020/presentation/DetailCityActivity.kt @@ -1,12 +1,16 @@ -package com.example.androidpractice2020.ui +package com.example.androidpractice2020.presentation import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope -import com.example.androidpractice2020.factory.InfoCity import com.example.androidpractice2020.R -import com.example.androidpractice2020.factory.ApiFactory +import com.example.androidpractice2020.data.WeatherApplication +import com.example.androidpractice2020.data.WeatherDao +import com.example.androidpractice2020.data.WeatherRepositoryImpl +import com.example.androidpractice2020.data.api.ApiFactory +import com.example.androidpractice2020.domain.FindCityUseCase import kotlinx.android.synthetic.main.activity_detail_city.* +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch class DetailCityActivity : AppCompatActivity() { @@ -14,27 +18,28 @@ class DetailCityActivity : AppCompatActivity() { private val api by lazy { ApiFactory.weatherApi } + private lateinit var findCityUseCase: FindCityUseCase override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_detail_city) val id = intent.getIntExtra("id", -1) - + findCityUseCase = FindCityUseCase((application as WeatherApplication).repository, Dispatchers.IO) loadCityWeather(id) } private fun loadCityWeather(id: Int) { lifecycleScope.launch { - api.getCityById(id).let { + findCityUseCase.findWeatherCityById(id).let { city_name.text = it.name - city_temp.text = it.main.temp.toString() + " ℃" - city_description.text = it.weather.get(0).description + city_temp.text = it.temp.toString() + " ℃" + city_description.text = it.description city_icon_geo.setImageResource(R.drawable.ic_geo_foreground) - number_humidity.text = "Влажность: ${it.main.humidity} %" + number_humidity.text = "Влажность: ${it.numbHumidity} %" - when (it.wind.deg.toDouble()) { + when (it.deg.toDouble()) { in 22.5..67.5 -> direction_wind.text = "Направление ветра: CB" in 112.5..157.5 -> direction_wind.text = "Направление ветра: ЮВ" in 202.5..247.5 -> direction_wind.text = "Направление ветра: ЮЗ" diff --git a/app/src/main/java/com/example/androidpractice2020/presentation/MainActivity.kt b/app/src/main/java/com/example/androidpractice2020/presentation/MainActivity.kt new file mode 100644 index 0000000..99176e1 --- /dev/null +++ b/app/src/main/java/com/example/androidpractice2020/presentation/MainActivity.kt @@ -0,0 +1,165 @@ +package com.example.androidpractice2020.presentation + +import android.Manifest +import android.content.Intent +import android.content.pm.PackageManager +import android.location.Location +import android.os.Bundle +import android.widget.SearchView +import androidx.appcompat.app.AppCompatActivity +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import androidx.lifecycle.lifecycleScope +import androidx.recyclerview.widget.DividerItemDecoration +import com.example.androidpractice2020.R +import com.example.androidpractice2020.data.City +import com.example.androidpractice2020.data.WeatherApplication +import com.example.androidpractice2020.domain.FindCityUseCase +import com.example.androidpractice2020.presentation.recyclerview.CityAdapter +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationServices +import com.google.android.material.snackbar.Snackbar +import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + + +class MainActivity : AppCompatActivity() { + + private lateinit var findCityUseCase: FindCityUseCase + + private var citiesList: ArrayList = arrayListOf() + + private lateinit var fusedLocationProviderClient: FusedLocationProviderClient + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + findCityUseCase = + FindCityUseCase((application as WeatherApplication).repository, Dispatchers.IO) + getPermissionGeoLocation() + + createSearchView() + } + + fun loadCityAroundUser( + latitude: Double, + longitude: Double, + //на будущее, если число городов будет меняться по решению пользователя + countCities: Int + ) { + lifecycleScope.launch { + findCityUseCase.findWeatherCitiesByCoordinates(latitude, longitude, countCities) + .let { + citiesList = it + + val list = city_list + list.addItemDecoration( + DividerItemDecoration( + this@MainActivity, + DividerItemDecoration.VERTICAL + ) + ) + + if (citiesList.size != 0) { + list.adapter = + CityAdapter( + citiesList + ) { + val intent = + Intent(this@MainActivity, DetailCityActivity::class.java) + intent.putExtra("id", it) + intent.putExtra("size", citiesList.size) + startActivity(intent) + } + } + } + } + } + + private fun createSearchView() { + search_view.setOnQueryTextListener(object : SearchView.OnQueryTextListener, + androidx.appcompat.widget.SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(cityName: String?): Boolean { + lifecycleScope.launch { + cityName?.let { + findCityUseCase.findWeatherCityByName(cityName).let { + if (it != null && it.id != -1) { + val intent = + Intent(this@MainActivity, DetailCityActivity::class.java) + intent.putExtra("id", it.id) + startActivity(intent) + } else { + Snackbar.make( + findViewById(android.R.id.content), + "Город с таким названием не найден", + Snackbar.LENGTH_LONG + ).show() + } + } + } + } + return false + } + + override fun onQueryTextChange(p0: String?): Boolean { + //вызовется при изменении ведённого текста + return true + } + }) + } + + private fun getPermissionGeoLocation() { + fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this) + var longitude = 37.6156 + var latitude = 55.7522 + val hasForegroundLocationPermission = + ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) + + if (hasForegroundLocationPermission == PackageManager.PERMISSION_GRANTED) { + fusedLocationProviderClient.lastLocation.addOnCompleteListener { task -> + var location: Location? = task.result + if (location == null) { + + loadCityAroundUser(latitude, longitude, 15) + } else { + longitude = location.longitude + latitude = location.latitude + + loadCityAroundUser(latitude, longitude, 15) + + } + } + + } else { + val REQUEST_CODE_PERMISSION_READ_CONTACTS = 1 + ActivityCompat.requestPermissions( + this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), + REQUEST_CODE_PERMISSION_READ_CONTACTS + ) + } +// var latitude = 0.0 +// var longitude = 0.0 +// val hasForegroundLocationPermission = +// ContextCompat.checkSelfPermission( +// applicationContext, +// Manifest.permission.ACCESS_FINE_LOCATION +// ) +// if (hasForegroundLocationPermission == PackageManager.PERMISSION_GRANTED) { +// findCityUseCase.getCoordinatesByUser(this@MainActivity, true).let { +// latitude = it[0] +// longitude = it[1] +// Log.e("qweqw2", "$latitude") +// Log.e("qweqwe2", "$longitude") +// } +// loadCityAroundUser(latitude, longitude, 15) +// } else { +// loadCityAroundUser(55.7522, 37.6156, 15) +// val REQUEST_CODE_PERMISSION_READ_CONTACTS = 1 +// ActivityCompat.requestPermissions( +// this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), +// REQUEST_CODE_PERMISSION_READ_CONTACTS +// ) +// } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidpractice2020/recyclerview/CityAdapter.kt b/app/src/main/java/com/example/androidpractice2020/presentation/recyclerview/CityAdapter.kt similarity index 64% rename from app/src/main/java/com/example/androidpractice2020/recyclerview/CityAdapter.kt rename to app/src/main/java/com/example/androidpractice2020/presentation/recyclerview/CityAdapter.kt index 00d1827..bb41444 100644 --- a/app/src/main/java/com/example/androidpractice2020/recyclerview/CityAdapter.kt +++ b/app/src/main/java/com/example/androidpractice2020/presentation/recyclerview/CityAdapter.kt @@ -1,10 +1,11 @@ -package com.example.androidpractice2020.recyclerview +package com.example.androidpractice2020.presentation.recyclerview import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView -import com.example.androidpractice2020.factory.InfoCity +import com.example.androidpractice2020.data.City -class CityAdapter(var list: ArrayList, var itemClick: (Int) -> Unit): RecyclerView.Adapter() { +class CityAdapter(var list: ArrayList, var itemClick: (Int) -> Unit) : + RecyclerView.Adapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CityHolder = CityHolder.create( diff --git a/app/src/main/java/com/example/androidpractice2020/recyclerview/CityHolder.kt b/app/src/main/java/com/example/androidpractice2020/presentation/recyclerview/CityHolder.kt similarity index 84% rename from app/src/main/java/com/example/androidpractice2020/recyclerview/CityHolder.kt rename to app/src/main/java/com/example/androidpractice2020/presentation/recyclerview/CityHolder.kt index 11a6c8c..cf43824 100644 --- a/app/src/main/java/com/example/androidpractice2020/recyclerview/CityHolder.kt +++ b/app/src/main/java/com/example/androidpractice2020/presentation/recyclerview/CityHolder.kt @@ -1,23 +1,23 @@ -package com.example.androidpractice2020.recyclerview +package com.example.androidpractice2020.presentation.recyclerview import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView -import com.example.androidpractice2020.factory.InfoCity import kotlinx.android.extensions.LayoutContainer import com.example.androidpractice2020.R +import com.example.androidpractice2020.data.City import kotlinx.android.synthetic.main.city_item.* class CityHolder(override val containerView: View, var itemClick: (Int) -> Unit) : RecyclerView.ViewHolder(containerView), LayoutContainer { - fun bind(city: InfoCity) { + fun bind(city: City) { text_name_list.text = city.name - text_temp_list.text = "${city.main.temp} \u2103" + text_temp_list.text = "${city.temp} \u2103" - when(city.main.temp) { + when(city.temp) { in -30.0..-18.0 -> text_temp_list.setTextColor(-65536) in -18.0..-6.0 -> text_temp_list.setTextColor(-256) in -6.0..6.0 -> text_temp_list.setTextColor(-16711681) diff --git a/app/src/main/java/com/example/androidpractice2020/recyclerview/City.kt b/app/src/main/java/com/example/androidpractice2020/recyclerview/City.kt deleted file mode 100644 index 387dea0..0000000 --- a/app/src/main/java/com/example/androidpractice2020/recyclerview/City.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.androidpractice2020.recyclerview - -data class City( - var id: Int, - var name: String, - var temp: Int -) diff --git a/app/src/main/java/com/example/androidpractice2020/ui/MainActivity.kt b/app/src/main/java/com/example/androidpractice2020/ui/MainActivity.kt deleted file mode 100644 index 8da30b2..0000000 --- a/app/src/main/java/com/example/androidpractice2020/ui/MainActivity.kt +++ /dev/null @@ -1,131 +0,0 @@ -package com.example.androidpractice2020.ui - -import android.Manifest -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.location.Location -import android.os.Bundle -import android.widget.SearchView -import androidx.appcompat.app.AppCompatActivity -import androidx.core.app.ActivityCompat -import androidx.core.content.ContextCompat -import androidx.lifecycle.lifecycleScope -import androidx.recyclerview.widget.DividerItemDecoration -import com.example.androidpractice2020.* -import com.example.androidpractice2020.factory.ApiFactory -import com.example.androidpractice2020.factory.InfoCity -import com.example.androidpractice2020.recyclerview.CityAdapter -import com.google.android.gms.location.FusedLocationProviderClient -import com.google.android.gms.location.LocationServices -import com.google.android.material.snackbar.Snackbar -import kotlinx.android.synthetic.main.activity_main.* -import kotlinx.coroutines.launch -import java.lang.Exception - - -class MainActivity : AppCompatActivity() { - lateinit var fusedLocationProviderClient: FusedLocationProviderClient - private val api by lazy { - ApiFactory.weatherApi - } - - private var citiesList: ArrayList = arrayListOf() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - - - - - search_view.setOnQueryTextListener(object: SearchView.OnQueryTextListener, - androidx.appcompat.widget.SearchView.OnQueryTextListener { - override fun onQueryTextSubmit(p0: String?): Boolean { - lifecycleScope.launch { - try { - p0?.let { - api.getWeather(it).let { - val intent = - Intent(this@MainActivity, DetailCityActivity::class.java) - intent.putExtra("id", it.id) - startActivity(intent) - } - } - } catch (e: Exception) { - Snackbar.make(findViewById(android.R.id.content), - "Город с таким названием не найден", - Snackbar.LENGTH_LONG - ).show() - } - } - return false - } - - override fun onQueryTextChange(p0: String?): Boolean { - //вызовется при изменении ведённого текста - return true - } - }) - } - - override fun onResume() { - locationConnect() - super.onResume() - } - - private fun loadCityAroundUser(context: Context, latitude: Double, longitude: Double) { - lifecycleScope.launch { - api.getCitiesWeather(latitude, longitude, 15).let { - citiesList = it.list as ArrayList - - val list = city_list - list.addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL)) - if (citiesList.size != 0) { - list.adapter = - CityAdapter( - citiesList - ) { - val intent = Intent(context, DetailCityActivity::class.java) - intent.putExtra("id", it) - intent.putExtra("size", citiesList.size) - startActivity(intent) - } - } - - } - } - } - - private fun locationConnect() { - fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this) - var longitude = 37.6156 - var latitude = 55.7522 - val hasForegroundLocationPermission = - ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) - - if (hasForegroundLocationPermission == PackageManager.PERMISSION_GRANTED) { - fusedLocationProviderClient.lastLocation.addOnCompleteListener { task -> - var location: Location? = task.result - if (location == null) { - - loadCityAroundUser(this, latitude, longitude) - - } else { - longitude = location.longitude - latitude = location.latitude - - loadCityAroundUser(this, latitude, longitude) - - } - } - - } else { - val REQUEST_CODE_PERMISSION_READ_CONTACTS = 1 - ActivityCompat.requestPermissions( - this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), - REQUEST_CODE_PERMISSION_READ_CONTACTS - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 96254e1..3279643 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,7 +5,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorPrimary" - tools:context=".ui.MainActivity"> + tools:context=".presentation.MainActivity"> Date: Mon, 1 Mar 2021 22:41:15 +0300 Subject: [PATCH 2/2] task/hw10_weather_application_continue2 --- app/src/main/AndroidManifest.xml | 2 +- .../application/WeatherApplication.kt | 20 +++++++++++++++++++ .../data/WeatherApplication.kt | 15 -------------- .../api/response/CitiesWeatherResponse.kt | 2 -- .../{ => database}/WeatherRoomDatabase.kt | 7 +++++-- .../data/{ => database/dao}/WeatherDao.kt | 3 ++- .../data/{ => database/entity}/City.kt | 3 +-- .../repository}/WeatherRepositoryImpl.kt | 4 +++- .../domain/FindCityUseCase.kt | 7 ++----- .../domain/WeatherRepository.kt | 2 +- .../presentation/DetailCityActivity.kt | 4 +--- .../presentation/MainActivity.kt | 4 ++-- .../presentation/recyclerview/CityAdapter.kt | 2 +- .../presentation/recyclerview/CityHolder.kt | 2 +- 14 files changed, 40 insertions(+), 37 deletions(-) create mode 100644 app/src/main/java/com/example/androidpractice2020/application/WeatherApplication.kt delete mode 100644 app/src/main/java/com/example/androidpractice2020/data/WeatherApplication.kt rename app/src/main/java/com/example/androidpractice2020/data/{ => database}/WeatherRoomDatabase.kt (74%) rename app/src/main/java/com/example/androidpractice2020/data/{ => database/dao}/WeatherDao.kt (84%) rename app/src/main/java/com/example/androidpractice2020/data/{ => database/entity}/City.kt (91%) rename app/src/main/java/com/example/androidpractice2020/data/{ => database/repository}/WeatherRepositoryImpl.kt (94%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8da3378..b756c80 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,7 +7,7 @@ , var itemClick: (Int) -> Unit) : RecyclerView.Adapter() { diff --git a/app/src/main/java/com/example/androidpractice2020/presentation/recyclerview/CityHolder.kt b/app/src/main/java/com/example/androidpractice2020/presentation/recyclerview/CityHolder.kt index cf43824..58f951a 100644 --- a/app/src/main/java/com/example/androidpractice2020/presentation/recyclerview/CityHolder.kt +++ b/app/src/main/java/com/example/androidpractice2020/presentation/recyclerview/CityHolder.kt @@ -6,7 +6,7 @@ import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import kotlinx.android.extensions.LayoutContainer import com.example.androidpractice2020.R -import com.example.androidpractice2020.data.City +import com.example.androidpractice2020.data.database.entity.City import kotlinx.android.synthetic.main.city_item.* class CityHolder(override val containerView: View, var itemClick: (Int) -> Unit) :