🍥구현 기능
- 전체 코드 다듬기
- 함수 파라미터 의미있는 이름을 갖도록 변경하기
- Scope function 적절하게 사용하기
- this 반환이 필요한 경우 apply 사용
- this 반환이 필요하지 않은 경우 run/with 사용
- 사용하지 않는 패키지 import 삭제하기
- Extra의 키 값 상수로 선언하기
- TextView 확장함수 삭제하기
- 이미 존재하는 isVisible 속성 이용해 구현하기
- EditText 입력 이벤트 처리 코드 변경하기
- TextWatcher 인터페이스를 구현하는 클래스들 삭제 -> function으로 변경하기
(NameTextWatcher, EmailTextWatcher, PasswordTextWatcher)
- companion object로 정의한 입력 값이 유효한지 저장하는 Boolean 변수들 삭제
(isNameValid, isPasswordValid, isEmailValid)
🍥구현하기
SignInActivity.kt
class SignInActivity : AppCompatActivity() {
private val TAG = "SignInActivity"
companion object{
val EXTRA_SIGN_UP_NAME = "extra_sign_up_name"
val EXTRA_SIGN_UP_PASSWORD = "extra_sign_up_password"
fun getResultIntent(signUpName:String, signUpPassword:String) :Intent =
Intent().apply {
putExtra(EXTRA_SIGN_UP_NAME, signUpName)
putExtra(EXTRA_SIGN_UP_PASSWORD, signUpPassword)
}
}
private val nameEditText by lazy { findViewById<EditText>(R.id.et_name) }
private val passwordEditText by lazy { findViewById<EditText>(R.id.et_password) }
private val nameWarningTextView by lazy { findViewById<TextView>(R.id.tv_name_warning) }
private val passwordWarningTextView by lazy { findViewById<TextView>(R.id.tv_password_warning) }
private val signInWarningTextView by lazy { findViewById<TextView>(R.id.tv_sign_in_warning) }
private val signInButton by lazy { findViewById<Button>(R.id.btn_sign_in) }
private val signUpButton by lazy { findViewById<Button>(R.id.btn_sign_up) }
private val userInfoManager = UserInfoManager.getInstance()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sign_in)
initNameEditText()
initPasswordEditText()
initSignInButton()
val startForResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
Log.d(TAG, "startForResultLauncher) RESULT_OK")
val intent = result.data
intent?.let {
val signUpName = it.getStringExtra(EXTRA_SIGN_UP_NAME) ?: " "
val signUpPassword = it.getStringExtra(EXTRA_SIGN_UP_PASSWORD) ?: " "
Log.d(TAG, "startForResultLauncher) $signUpName $signUpPassword")
nameEditText.setText(signUpName)
passwordEditText.setText(signUpPassword)
}
}
}
initSignUpButton(startForResultLauncher)
}
private fun initNameEditText() {
nameEditText.addTextChangedListener { text ->
nameWarningTextView.run {
if (text.isNullOrBlank()) {
setText(R.string.empty_name_warning)
isVisible = true
} else {
isVisible = false
}
}
}
}
private fun initPasswordEditText() {
passwordEditText.addTextChangedListener { text ->
passwordWarningTextView.run {
if (text.isNullOrBlank()) {
setText(R.string.empty_password_warning)
setTextColor(resources.getColor(R.color.warning_color))
isVisible = true
} else {
isVisible = false
}
}
}
}
private fun isNameValid(): Boolean {
return !nameEditText.text.isNullOrBlank()
}
private fun isPasswordValid(): Boolean {
return !passwordEditText.text.isNullOrBlank()
}
private fun initSignInButton() {
signInButton.setOnClickListener {
signInWarningTextView.run {
if (!isNameValid()) {
Log.d(TAG, "sign in button) name is empty")
text = resources.getText(R.string.empty_name_warning)
isVisible = true
return@setOnClickListener
}
if (!isPasswordValid()) {
Log.d(TAG, "sign in button) password is empty")
text = resources.getText(R.string.empty_password_warning)
isVisible = true
return@setOnClickListener
}
}
val name = nameEditText.text.toString()
val password = passwordEditText.text.toString()
if (userInfoManager.signIn(name, password)) {
Log.d(TAG, "sign in button) sign in success")
signInWarningTextView.isVisible = false
startActivity(HomeActivity.newIntent(this, name, password))
} else {
Log.d(TAG, "sign in button) sign in fail")
signInWarningTextView.text = resources.getText(R.string.sign_in_fail_warning)
signInWarningTextView.isVisible = true
}
}
}
private fun initSignUpButton(startForResultLauncher:ActivityResultLauncher<Intent>){
signUpButton.setOnClickListener {
val intent = Intent(applicationContext, SignUpActivity::class.java)
startForResultLauncher.launch(intent)
}
}
}
SignUpActivity.kt
class SignUpActivity : AppCompatActivity() {
private val TAG = "SignUpActivity"
private val nameEditText by lazy { findViewById<EditText>(R.id.et_name) }
private val nameWarningTextView by lazy { findViewById<TextView>(R.id.tv_name_warning) }
private val emailEditText by lazy { findViewById<EditText>(R.id.et_email) }
private val emailProviderEditText by lazy { findViewById<EditText>(R.id.et_email_provider) }
private val emailProviderSpinner by lazy { findViewById<Spinner>(R.id.spinner_email_provider) }
private val emailWarningTextView by lazy { findViewById<TextView>(R.id.tv_email_warning) }
private val passwordEditText by lazy { findViewById<EditText>(R.id.et_password) }
private val passwordWarningTextView by lazy { findViewById<TextView>(R.id.tv_password_warning) }
private val passwordCheckEditText by lazy { findViewById<EditText>(R.id.et_password_check) }
private val passwordCheckWarningTextView by lazy { findViewById<TextView>(R.id.tv_password_check_warning) }
private val signUpWarningTextView by lazy { findViewById<TextView>(R.id.tv_sign_up_warning) }
private val signUpButton by lazy { findViewById<Button>(R.id.btn_sign_up) }
private val userInfoManager = UserInfoManager.getInstance()
private var isNameValid = false
private var isEmailValid = false
private var isPasswordValid = false
private var isPasswordCheckValid = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sign_up)
initNameEditText()
initEmailEditText()
initPasswordEditText()
initPasswordCheckEditText()
initEmailProviderSpinner()
initSignUpButton()
}
private fun initNameEditText() {
nameEditText.addTextChangedListener { text ->
nameWarningTextView.run {
if (text.isNullOrBlank()) {
setText(R.string.empty_name_warning)
isVisible = true
isNameValid = false
}
else if (userInfoManager.findSameName(text.toString())) {
setText(R.string.same_name_warning)
isVisible = true
isNameValid = false
} else {
isVisible = false
isNameValid = true
}
}
}
}
private fun initEmailEditText() {
emailEditText.addTextChangedListener { text ->
emailWarningTextView.isVisible = text.isNullOrBlank()
isEmailValid = !text.isNullOrBlank()
}
}
private fun initPasswordEditText() {
passwordEditText.addTextChangedListener { text ->
passwordWarningTextView.apply {
if (text.isNullOrBlank()) {
setText(R.string.empty_password_warning)
setTextColor(resources.getColor(R.color.warning_color))
isVisible = true
isPasswordValid = false
}
else if (text.length < 10) {
setText(R.string.password_length_information)
setTextColor(resources.getColor(R.color.information_color))
isVisible = true
isPasswordValid = false
}
else if (!containsUppercase(text.toString())) {
setText(R.string.password_uppercase_information)
setTextColor(resources.getColor(R.color.information_color))
isVisible = true
isPasswordValid = false
}
else if (!containsSpecialChar(text.toString())) {
setText(R.string.password_special_char_information)
setTextColor(resources.getColor(R.color.information_color))
isVisible = true
isPasswordValid = false
} else {
isVisible = false
isPasswordValid = true
}
}
}
}
private fun containsUppercase(password: String): Boolean {
for (ch in password) {
if (('A'.code <= ch.code) && (ch.code <= 'Z'.code)) return true
}
return false
}
private fun containsSpecialChar(password: String): Boolean {
val possibleSpecialChars =
listOf('!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+', '=')
for (ch in password) {
if (possibleSpecialChars.contains(ch)) return true
}
return false
}
private fun initPasswordCheckEditText() {
passwordCheckEditText.addTextChangedListener { text ->
passwordCheckWarningTextView.apply {
if (text.isNullOrBlank()) {
setText(R.string.empty_password_warning)
isVisible = true
isPasswordCheckValid = false
}
else if (text.toString() != passwordEditText.text.toString()) {
setText(R.string.password_different_warning)
isVisible = true
isPasswordCheckValid = false
} else {
isVisible = false
isPasswordCheckValid = true
}
}
}
}
private fun initEmailProviderSpinner(){
ArrayAdapter.createFromResource(
this,
R.array.email_providers_array,
android.R.layout.simple_spinner_item
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
emailProviderSpinner.adapter = adapter
}
emailProviderSpinner.onItemSelectedListener = spinnerOnItemSelectListener
}
private val spinnerOnItemSelectListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(p0: AdapterView<*>?, view: View?, position: Int, id: Long) {
Log.d(TAG, "email provider spinner) onItemSelected")
if (position == emailProviderSpinner.adapter.count - 1) {
emailProviderSpinner.visibility = View.GONE
emailProviderEditText.visibility = View.VISIBLE
}
}
override fun onNothingSelected(p0: AdapterView<*>?) {
Log.d(TAG, "email provider spinner) onNothingSelected")
}
}
private fun initSignUpButton(){
signUpButton.setOnClickListener {
if (isNameValid && isEmailValid && isPasswordValid && isPasswordCheckValid) {
Log.d(TAG, "sign up button) sign up success")
signUpWarningTextView.isVisible = false
val name = nameEditText.text.toString()
val password = passwordEditText.text.toString()
var email = emailEditText.text.toString()
email += if (emailProviderSpinner.visibility == View.VISIBLE) {
emailProviderSpinner.selectedItem.toString()
} else {
emailProviderEditText.text?.toString() ?: ""
}
val userInfoManager = UserInfoManager.getInstance()
userInfoManager.signUp(name, email, password)
finishSignUpActivity(name, password)
} else {
Log.d(TAG, "sign up button) sign up fail")
signUpWarningTextView.isVisible = true
} }
}
private fun finishSignUpActivity(name: String, password: String) {
setResult(Activity.RESULT_OK, SignInActivity.getResultIntent(name,password))
finish()
}
}
HomeActivity.kt
class HomeActivity : AppCompatActivity() {
private val TAG = "HomeActivity"
companion object{
val EXTRA_NAME = "extra_name"
val EXTRA_PASSWORD = "extra_password"
fun newIntent(context: Context, name:String, password:String): Intent =
Intent(context, HomeActivity::class.java).apply {
putExtra(EXTRA_NAME, name)
putExtra(EXTRA_PASSWORD, password)
}
}
private val homeImageView:ImageView by lazy{findViewById(R.id.iv_home)}
private val imageButton:Button by lazy{findViewById(R.id.btn_image)}
private val nameTextView:TextView by lazy{findViewById(R.id.tv_home_name)}
private val emailTextView:TextView by lazy {findViewById(R.id.tv_home_email)}
private val exitButton: Button by lazy{findViewById(R.id.btn_exit)}
private var isImageUploaded = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
setHomeImageViewRandom()
val pickMedia = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
if (uri != null) {
Log.d(TAG, "Photo Picker) Selected URI: $uri")
setHomeImageView(uri)
setImageButtonUpload(false)
} else {
Log.d(TAG, "Photo Picker) No media selected")
}
}
imageButton.setOnClickListener {
if(!isImageUploaded){
pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}
else{
setHomeImageViewRandom()
setImageButtonUpload(true)
}
}
val name = intent.getStringExtra(EXTRA_NAME)!!
val password = intent.getStringExtra(EXTRA_PASSWORD)!!
val email = UserInfoManager.getInstance().findUserEmail(name, password)
nameTextView.text = resources.getString(R.string.home_name, name)
emailTextView.text = resources.getString(R.string.home_email, email)
exitButton.setOnClickListener {
finish()
}
}
private fun setHomeImageViewRandom(){
val imageNumber:Int = Random.nextInt(5)+1
val imageId = resources.getIdentifier("ham${imageNumber}", "drawable", packageName)
homeImageView.setImageResource(imageId)
}
private fun setHomeImageView(uri:Uri){
homeImageView.setImageURI(uri)
}
private fun setImageButtonUpload(flag:Boolean){
if(flag) {
isImageUploaded = false
imageButton.text = getString(R.string.upload_image)
}
else{
isImageUploaded = true
imageButton.text = getString(R.string.delete_image)
}
}
}