Skip to content
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
32 changes: 29 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
id 'com.google.dagger.hilt.android'
id 'org.jetbrains.kotlin.plugin.serialization' version "1.8.10"
}

android {
namespace 'ru.otus.basicarchitecture'
compileSdk 33

buildFeatures {
buildConfig = true
}

viewBinding{
enabled = true
}

defaultConfig {
applicationId "ru.otus.basicarchitecture"
minSdk 24
Expand All @@ -15,6 +26,8 @@ android {
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

buildConfigField("String","API_KEY","\"${project.API_KEY}\"")
}

buildTypes {
Expand All @@ -24,11 +37,11 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = '17'
}
}

Expand All @@ -38,7 +51,20 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation "com.google.dagger:hilt-android:2.44"
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1'
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
implementation "com.squareup.retrofit2:retrofit:2.9.0"
kapt "com.google.dagger:hilt-compiler:2.44"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

kapt {
correctErrorTypes true
}
11 changes: 9 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

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

<application
android:name=".App"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Expand All @@ -14,7 +17,11 @@
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="false" />
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
8 changes: 8 additions & 0 deletions app/src/main/java/ru/otus/basicarchitecture/App.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ru.otus.basicarchitecture

import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class App: Application() {
}
12 changes: 12 additions & 0 deletions app/src/main/java/ru/otus/basicarchitecture/DataCache.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ru.otus.basicarchitecture

import dagger.hilt.android.scopes.ActivityRetainedScoped
import javax.inject.Inject
@ActivityRetainedScoped
class DataCache @Inject constructor() {
var name: String = ""
var surname: String = ""
var dateOfBirth: String = ""
var address: String = ""
var interests: List<String> = listOf()
}
14 changes: 13 additions & 1 deletion app/src/main/java/ru/otus/basicarchitecture/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,22 @@ package ru.otus.basicarchitecture

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import dagger.hilt.android.AndroidEntryPoint
import ru.otus.basicarchitecture.databinding.ActivityMainBinding
import ru.otus.basicarchitecture.name.NameFragment

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding:ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

if(savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, NameFragment())
.commit()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package ru.otus.basicarchitecture.address

import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import androidx.fragment.app.Fragment
import dagger.hilt.android.AndroidEntryPoint
import ru.otus.basicarchitecture.interests.InterestsFragment
import ru.otus.basicarchitecture.R
import ru.otus.basicarchitecture.databinding.FragmentAddressBinding
import ru.otus.basicarchitecture.net.AddressValue
import javax.inject.Inject

@AndroidEntryPoint
class AddressFragment: Fragment() {

private lateinit var binding: FragmentAddressBinding

@Inject
lateinit var viewModel: AddressFragmentViewModel

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentAddressBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

binding.address.addTextChangedListener(object: TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(editable: Editable?) {
viewModel.search(editable.toString())
}
})

viewModel.getResultAddressLive().observe(viewLifecycleOwner) {
if(it != null) {
val adapter = ArrayAdapter(
requireContext(),
android.R.layout.simple_list_item_1,
it.map(AddressValue::value)
)
binding.address.setAdapter(adapter)
}
}
binding.buttonNext2.setOnClickListener(){
viewModel.save(binding.address.text.toString())

parentFragmentManager.beginTransaction()
.replace(R.id.container, InterestsFragment())
.addToBackStack(null)
.commit()
}
}

override fun onDestroyView() {
super.onDestroyView()
viewModel.cancel()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package ru.otus.basicarchitecture.address

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import ru.otus.basicarchitecture.DataCache
import ru.otus.basicarchitecture.net.AddressService
import ru.otus.basicarchitecture.net.AddressValue
import javax.inject.Inject

class AddressFragmentViewModel @Inject constructor(
private val dataCache: DataCache
) : ViewModel(){

@Inject lateinit var service : AddressService
private var activeJob: Job? = null
private val resultAddressLive = MutableLiveData<List<AddressValue>?>()

fun save (address: String) {
dataCache.address = address
}

fun search(query: String) {
activeJob = viewModelScope.launch {
try {
service.request(query) { response ->
resultAddressLive.value = response?.suggestions
}
} catch (e: Exception) {
resultAddressLive.value = emptyList()
Log.e("Error: ", e.message.toString())
}
}
}

fun cancel() {
activeJob?.cancel()
activeJob = null
}
fun getResultAddressLive(): LiveData<List<AddressValue>?> {
return resultAddressLive
}
}
47 changes: 47 additions & 0 deletions app/src/main/java/ru/otus/basicarchitecture/info/InfoFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package ru.otus.basicarchitecture.info

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.google.android.material.chip.Chip
import dagger.hilt.android.AndroidEntryPoint
import ru.otus.basicarchitecture.databinding.FragmentInfoBinding
import javax.inject.Inject

@AndroidEntryPoint
class InfoFragment: Fragment() {

private lateinit var binding: FragmentInfoBinding

@Inject
lateinit var viewModel: InfoFragmentViewModel

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentInfoBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

binding.nameInfo.text = viewModel.dataCache.name
binding.surnameInfo.text = viewModel.dataCache.surname
binding.birthDateInfo.text = viewModel.dataCache.dateOfBirth
binding.addressInfo.text = viewModel.getAddressInfo()

viewModel.dataCache.interests.forEach {
Chip(context).apply {
text = it
isClickable = false
isCheckable = false
binding.chipGroupInfo.addView(this)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ru.otus.basicarchitecture.info

import androidx.lifecycle.ViewModel
import ru.otus.basicarchitecture.DataCache
import javax.inject.Inject

class InfoFragmentViewModel @Inject constructor(
val dataCache: DataCache
) : ViewModel(){

fun getAddressInfo():String {
val addressResult = StringBuilder()
if (dataCache.address != "") addressResult.append(dataCache.address)
return addressResult.toString()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package ru.otus.basicarchitecture.interests

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.google.android.material.chip.Chip
import dagger.hilt.android.AndroidEntryPoint
import ru.otus.basicarchitecture.R
import ru.otus.basicarchitecture.databinding.FragmentInterestsBinding
import ru.otus.basicarchitecture.info.InfoFragment
import javax.inject.Inject


@AndroidEntryPoint
class InterestsFragment: Fragment() {

private lateinit var binding: FragmentInterestsBinding

@Inject
lateinit var viewModel: InterestsFragmentViewModel

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentInterestsBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

binding.next.setOnClickListener {
viewModel.save()
parentFragmentManager.beginTransaction()
.replace(R.id.container, InfoFragment::class.java, null)
.addToBackStack(null)
.commit()
}

viewModel.interestsList.forEach { chip ->
Chip(context).apply {
text = chip
isClickable = true
isCheckable = true
isChecked = viewModel.selectedInterests.value?.contains(chip) ?: false
setOnCheckedChangeListener{ _, isChecked ->
viewModel.addOrRemoveInterest(chip)
}
binding.chipGroup.addView(this)
}
}
}
}
Loading