Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add coroutine #10

Open
wants to merge 16 commits into
base: develop/view
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
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ android {
}

dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")
implementation 'com.jakewharton.timber:timber:5.0.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
// ViewModel 생성함수를 편하게 사용하고 싶다면?
implementation "androidx.fragment:fragment-ktx:1.5.3"
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
android:theme="@style/Theme.INSOPTAndroidPractice"
tools:targetApi="31">
<activity
android:name=".SignInActivity"
android:name=".presentation.SignInActivity"
Copy link
Member

Choose a reason for hiding this comment

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

패키지 나눈거 좋아용!!

android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
49 changes: 18 additions & 31 deletions app/src/main/java/org/sopt/sample/HomeFragment.kt
Original file line number Diff line number Diff line change
@@ -1,46 +1,33 @@
package org.sopt.sample

import org.sopt.sample.adapter.rvAdapter
import org.sopt.sample.databinding.FragmentHomeBinding
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.google.android.material.snackbar.Snackbar
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import org.sopt.sample.adapter.rvAdapter
import org.sopt.sample.base.BindingFragment
import org.sopt.sample.databinding.FragmentSearchBinding
import org.sopt.sample.remote.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import org.sopt.sample.databinding.FragmentHomeBinding
import org.sopt.sample.user.UserRepository
import org.sopt.sample.user.UserViewModel
import org.sopt.sample.user.UserViewModelFactory

class HomeFragment: BindingFragment<FragmentHomeBinding>(R.layout.fragment_home) {
private var _binding : FragmentHomeBinding? = null
get() = requireNotNull(_binding)
private val userService = UserServicePool.userService
class HomeFragment : BindingFragment<FragmentHomeBinding>(R.layout.fragment_home) {
private lateinit var viewModel: UserViewModel

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(this, UserViewModelFactory(UserRepository()))
.get(UserViewModel::class.java)
binding.viewModel = viewModel
binding.lifecycleOwner = this

val adapter = rvAdapter(requireContext())
binding.rvRepos.adapter = adapter
userService.user().enqueue(object : Callback<ResponseUserDTO> {
override fun onResponse(
call: Call<ResponseUserDTO>,
response: Response<ResponseUserDTO>
) {
Log.d("유저 정보", "${response.body()}")
if (response.isSuccessful) {
response.body()?.let {
adapter.setRepoList(it.data)
}
}
}

override fun onFailure(call: Call<ResponseUserDTO>, t: Throwable) {
Snackbar.make(binding.root, "서버통신 실패", Snackbar.LENGTH_LONG).show()
}
viewModel.fatchUser()

viewModel.userInfo.observe(viewLifecycleOwner, Observer {
Copy link
Member

Choose a reason for hiding this comment

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

위에 adapter 설정해주는 부분은 initLayout()으로, 이 부분은 addObservers함수로 로직 분리해주면 좋을 거같아용!

adapter.setRepoList(it)
})
}
}
1 change: 1 addition & 0 deletions app/src/main/java/org/sopt/sample/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.fragment.app.FragmentContainerView
import com.google.android.material.bottomnavigation.BottomNavigationView
import org.sopt.sample.base.BindingActivity
import org.sopt.sample.databinding.ActivityMainBinding
import timber.log.Timber

class MainActivity :BindingActivity<ActivityMainBinding>(R.layout.activity_main){
private val frame: FragmentContainerView by lazy { // activity_main의 화면 부분
Expand Down
31 changes: 0 additions & 31 deletions app/src/main/java/org/sopt/sample/SignInActivity.kt

This file was deleted.

100 changes: 18 additions & 82 deletions app/src/main/java/org/sopt/sample/SignUpActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,104 +2,40 @@ package org.sopt.sample

import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import androidx.activity.viewModels
import androidx.core.content.ContextCompat
import android.widget.Toast
import androidx.lifecycle.ViewModelProvider
import org.sopt.sample.base.BindingActivity
import org.sopt.sample.databinding.ActivitySignUpBinding
import org.sopt.sample.presentation.SignInActivity
import org.sopt.sample.signup.SignupRepository
import org.sopt.sample.signup.SignupViewModel
import java.util.regex.Pattern
import org.sopt.sample.signup.SignupViewModelFactory


class SignUpActivity : BindingActivity<ActivitySignUpBinding>(R.layout.activity_sign_up) {
private val viewModel by viewModels<SignupViewModel>()
private lateinit var viewModel: SignupViewModel

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this, SignupViewModelFactory(SignupRepository()))
.get(SignupViewModel::class.java)
binding.viewModel = viewModel
binding.lifecycleOwner = this

// 버튼 클릭 이벤트
var validEmail = false
var validPw = false
val EmailPattern = "^(?=.*[A-Za-z])(?=.*[0-9])[A-Za-z[0-9]]{6,10}$"
val pattern1 = Pattern.compile(EmailPattern)
val PwPattern = "^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[$@$!%*#?&.])[A-Za-z[0-9]$@$!%*#?&.]{6,12}$"
val pattern2 = Pattern.compile(PwPattern)



binding.editTextEmail.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
// 입력난에 변화가 있을 시 조치
viewModel.inputEmail.value = binding.editTextEmail.text.toString()
}
override fun afterTextChanged(arg0: Editable) {
// 입력이 끝났을 때 조치
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
// 입력하기 전에 조치
}
})

binding.editTextPw.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
// 입력난에 변화가 있을 시 조치
viewModel.inputPw.value = binding.editTextPw.text.toString()
}
override fun afterTextChanged(arg0: Editable) {
// 입력이 끝났을 때 조치
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
// 입력하기 전에 조치
}
})

viewModel.inputEmail.observe(this) {
val matcher1 = pattern1.matcher(it)
if(matcher1.find() == true) {
validEmail = true
binding.editTextEmail.backgroundTintList =
ContextCompat.getColorStateList(applicationContext, R.color.edit_gray)
}
if(validEmail == false) {
binding.tvEmailerror.visibility = View.VISIBLE
binding.editTextEmail.backgroundTintList = ContextCompat.getColorStateList(applicationContext, R.color.red)
}
if(validEmail == true)
binding.tvEmailerror.visibility = View.INVISIBLE
if(validEmail == true && validPw == true)
binding.finishBtn.isEnabled = true
}

viewModel.inputPw.observe(this) {
val matcher2 = pattern2.matcher(it)
if(matcher2.find() == true) {
validPw = true
binding.editTextPw.backgroundTintList =
ContextCompat.getColorStateList(applicationContext, R.color.edit_gray)
}
if(validPw == false) {
binding.tvPwerror.visibility = View.VISIBLE
binding.editTextPw.backgroundTintList = ContextCompat.getColorStateList(applicationContext, R.color.red)
}
if(validPw == true)
binding.tvPwerror.visibility = View.INVISIBLE
if(validEmail == true && validPw == true)
binding.finishBtn.isEnabled = true
}
addListeners()
addObservers()
}

private fun addListeners(){
binding.finishBtn.setOnClickListener {
viewModel.signup(
binding.editTextEmail.text.toString(),
binding.editTextPw.text.toString(),
binding.editTextName.text.toString()
)
viewModel.signup()
}
}

private fun addObservers() {
viewModel.signupResult.observe(this) {
startActivity(Intent(this,SignInActivity::class.java))
startActivity(Intent(this, SignInActivity::class.java))
Toast.makeText(this,getString(R.string.sign_up_success_toast_msg), Toast.LENGTH_LONG).show()
}
}
}
5 changes: 2 additions & 3 deletions app/src/main/java/org/sopt/sample/adapter/HeaderViewHolder.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package org.sopt.sample.adapter

import androidx.recyclerview.widget.RecyclerView
import org.sopt.sample.data.Repo
import org.sopt.sample.databinding.LayoutHeaderBinding
import org.sopt.sample.databinding.ItemHeaderBinding

class TitleViewHolder (
private val binding: LayoutHeaderBinding
private val binding: ItemHeaderBinding
): RecyclerView.ViewHolder(binding.root){

}
10 changes: 4 additions & 6 deletions app/src/main/java/org/sopt/sample/adapter/RepoViewHolder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ package org.sopt.sample.adapter

import androidx.recyclerview.widget.RecyclerView
import coil.api.load
import org.sopt.sample.databinding.LayoutGithubRepoBinding
import org.sopt.sample.data.UserData
import org.sopt.sample.databinding.ItemUserInfoBinding
import org.sopt.sample.remote.ResponseUserDTO

class RepoViewHolder(
private val binding: LayoutGithubRepoBinding
private val binding: ItemUserInfoBinding
): RecyclerView.ViewHolder(binding.root){
fun onBind(data: ResponseUserDTO.Data){
binding.imgGithub.load(data.avatar)
binding.txtGithubName.setText(data.first_name)
binding.txtGithubAuthor.setText(data.email)
binding.data = data
}

}
9 changes: 5 additions & 4 deletions app/src/main/java/org/sopt/sample/adapter/rvAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import org.sopt.sample.databinding.LayoutGithubRepoBinding
import org.sopt.sample.databinding.LayoutHeaderBinding
import org.sopt.sample.data.UserData
import org.sopt.sample.databinding.ItemHeaderBinding
import org.sopt.sample.databinding.ItemUserInfoBinding
import org.sopt.sample.remote.ResponseUserDTO

class rvAdapter(context : Context):RecyclerView.Adapter<RecyclerView.ViewHolder>() {
Expand All @@ -15,11 +16,11 @@ class rvAdapter(context : Context):RecyclerView.Adapter<RecyclerView.ViewHolder>
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when(viewType){
REPO_TYPE ->{
val binding = LayoutGithubRepoBinding.inflate(inflater, parent,false)
val binding = ItemUserInfoBinding.inflate(inflater, parent,false)
Copy link
Member

Choose a reason for hiding this comment

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

네이밍 좋습니다 :)

RepoViewHolder(binding)
}
HEADER_TYPE ->{
val binding = LayoutHeaderBinding.inflate(inflater, parent,false)
val binding = ItemHeaderBinding.inflate(inflater, parent,false)
TitleViewHolder(binding)
}
else -> throw RuntimeException("Error")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package org.sopt.sample.data

import androidx.annotation.DrawableRes

data class Repo (
data class UserData (
@DrawableRes val image : Int,
val name: String,
val author: String,
val email: String,
val viewType: Int)
{
companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.sample.data.datasource

import org.sopt.sample.remote.RequestLoginDTO
import org.sopt.sample.remote.ResponseLoginDTO
import org.sopt.sample.remote.ServicePool

class LoginDataSource(private val service: ServicePool) {
suspend fun login(requestLoginDTO: RequestLoginDTO): ResponseLoginDTO =
service.loginService.login(requestLoginDTO)
}
Copy link
Member

Choose a reason for hiding this comment

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

저도 DataSource클래스 만들어서 다시 코드 정리해볼게요!!

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.sopt.sample.data.repositoryImpl

import org.sopt.sample.data.datasource.LoginDataSource
import org.sopt.sample.domain.LoginRepository
import org.sopt.sample.remote.RequestLoginDTO
import timber.log.Timber

class LoginRepositoryImpl(
private val loginDataSource: LoginDataSource
): LoginRepository {
override suspend fun login(email: String, password: String) : Boolean =
kotlin.runCatching {
loginDataSource.login(RequestLoginDTO(email, password))
}.fold({
Timber.d("로그인 서버통신 성공")
true
}, {
Timber.d("로그인 서버통신 실패")
false
})
}
5 changes: 5 additions & 0 deletions app/src/main/java/org/sopt/sample/domain/LoginRepository.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.sopt.sample.domain

interface LoginRepository {
suspend fun login(email: String, password: String) : Boolean
}
Loading