2018년 12월 27일 목요일

[Android]EditText 에서 disits 설정 시 오류 현상과 해결방법

안녕하세요.

disits 속성 사용 시 키보드 오류에 대해 말해 볼까 합니다.

개발을 하다보면 여러 변수가 생기고 거기에 맞게 대응 해야 되는데 그러기가 만만치 않습니다.

이번에 좀 당황하게 만들었던 일은 EditText의 inputType 속성으로는 부족함이 있어 disits 속성을 사용 하면서 생겼습니다.

많은 버전을 Test 하지는 않았지만 6.0 버전에서 disits 속성을 설정 하고 Test 해본 결과 원하는데로 작동하지 않았습니다.

증상은 EditText에서 disits로 설정하지 않은 값을 입력 할 시 EditText에 입력된 값이 복사 되는 현상과 disits에 설정된 값이 입력되지 않는 현상 으로 볼 수 있습니다.

결론 부터 말하자면 구글의 기본  키보드 오류 인거 같습니다. 단어를 제안 해주는 과정에서 오류가 생기는거 같으나 자세하게 보지는 않았습니다. 추측 입니다.

일단 해결은 android:inputType="textNoSuggestions|textCapCharacters" 으로 해결 했습니다. 

inputType 속성 중 textNoSuggestions을 설정해 텍스트 제안을 안하도록 설정하니 원하는데로 동작 하였습니다.

저는 추가적으로 대문자로만 입력 받고 싶어서 textCapCharacters도 입력 했습니다.

이런 현상은 8.1 버전에서는 발생 하지 않았으며 6.0 버전 에서만 발생 하였습니다. 이게 버전 문제인지는 좀 더 Test 해봐야겠지만 간단한 제안 정도는 xml 속성을 이용해서 처리 가능 합니다.






2018년 10월 30일 화요일

[Android] LifeCycle의 중요성!

안드로이드 개발을 할때 잘 생각해야 되는 부분 중 하나가 LifeCycle이 아닌가 생각 합니다. 

예전에 Fragment 생명주기도 포스팅 했지만 기본에 충실 하자는 의미로 Android의 기본적인 LifeCycle에 대해 포스팅 하려고 합니다.

기본적인 Activity의 LifeCyle은 아래 그림과 같습니다.


출처:https://developer.android.com



Android 개발 시 LifeCycle을 정확히 이해하고 개발 해야만 App이 의도한 대로 동작 하게 됩니다.

onCreate() 에서 객체생성 및 초기화 작업을 해주며 onDestory() 에서 메모리 누수가 예상 되는 객체는 해제를 해줘야 됩니다.

몇가지 상황을 예를 들어 설명 하자면

1. onResume() 과 onPause()는 App이 실행 되는 순간에도 자주 왔다갔다 합니다. 

onPause()는 잠시 대기 상태라고 생각해도 좋으며 보통 다이어로그가 화면에 보여질때나, 상태창 같은 창을 볼때도 onPause()가 호출 되게 됩니다. 

2. 앱이 실행 됐다가 홈 버튼을 누른다던지, 다른앱이 실행 되면 onPause() -> onStop() 메서드가 호출 되며, 다시 실행 할때는 onRestart() -> onStart() -> onResume() 순서로 호출 됩니다.

3. App이 강제 종료된 상태로 onPause() -> onStop() -> onCreate() -> onStart() -> onResume() 순으로 호출 됩니다.
여기서 유심히 살펴봐야 될 부분이 onStop() 이후 onCreate()가 호출 된다는 것입니다. 
onDestory()는 생략되고 onRestart()가 아닌 Activity의 시작인 onCreate()부터 새로 시작되는걸 볼 수 있습니다.

이렇듯 여러 상황에 대비 하여 적절한 처리를 수행 해야 됩니다.



그럼 어떤 방식으로 적절하게 상태를 유지 시켜 줄 수 있는지 알아 보겠습니다.

객체의 해제는 onStop(), onDestory()에서 적절하게 해주면 되며, Data의 상태 저장인 경우는 onSaveInstanceState()와 onRestoreInstanceState() 를 살펴볼 필요가 있습니다.

onSaveInstanceState()는 onPause()와 onStop()사이에서 항상 호출 되며, onRestoreInstanceState()는 강제 종료시에만 호출 되는 메서드 입니다. 

이러한 메서드는 LifeCycle에는 포함되어 있지 않지만, App의 상태유지를 위해서 반드시 알고 있어야 하는 메서드 입니다. 

물론 요세는 Android Architecture Component 개념을 활용 하여 화면 회전에 대한 처리를 해결할 수 있지만 위와 같은 기본적인 개념을 완전히 이해한 후 유용한 Architecture를 도입 한다면 좀 더 안정적인 App을 만들수 있을꺼라 생각 합니다. 












2018년 10월 23일 화요일

[Android] ConstraintLayout 사용에 익숙해 지자.

이 포스팅의 목적은 ConstraintLayout를 전부 알리고자 하는 목적이 아닌, 기본 속성만이라도 제대로 알고 조금씩이라도 활용도를 높이면 좋겠다는 생각으로 포스팅 합니다.

Android Studio에서 Project를 새로 생성하던지, Activity를 새로 생성 하던지, Layout를 생성하면 기본으로 생성되는 Layout이 ConstraintLayout 입니다.

평소에는 ConstraintLayout을 지우고 익숙한 LinearLayout 이나 RelativeLayout로 작업을 했지만, 매번 바꾸는 것도 귀찮고 해서 ConstraintLayout을 살펴 보았습니다.

사실 LinearLayout이 익숙하기 때문에 많이 사용 하지만 다른 Layout에 비하여 성능이 떨어지는 측면이 있다는걸 알고 있을 겁니다.

LinearLayout 자체가 성능이 떨어지는게 아니라, LinearLayout을 사용 하게 되면 어쩔 수 없이 한 레벨씩 안으로 들어 가면서 UI를 구성하게 됩니다.

모든 UI는 같은 레벨에서 작성될때 성능이 좀 더 나오는데 그런면에서 RelativeLayout를 한동안 사용 하기도 했습니다.

하지만 요세 Device 성능이 워낙 좋아서 정말 많은 레벨을 요구하지 않는 이상 일반적인 앱을 개발할 때에는 크게 신경 안써도 되지 않을까 생각합니다.

하지만!! 그래도!! 이왕이면!!


같은 레벨에서 작성하는게 조금이라도 성능 개선이 된다고 하니 ConstraintLayout에 대해서 알아보겠습니다.

오늘 포스팅할 내용은 위에서도 말씀 드렸지만  ConstraintLayout의 전체전인 부분이 아니라 기본적인 속성 입니다. 

그 이유는 처음부터 많은 속성을 보고 하나하나 적용 하는것도 의미가 있겠지만,
그것보다는 기본적인 핵심 특성만 보고 프로젝트에 조금씩 적용 하다 보면 점점 ConstraintLayout에 적응할 수 있지 않을까 해서 입니다.


가장 기본적인 속성입니다.

가장 기본적이면서도 가장 많이 사용 하며, 응용 하기에 따라 이정도만 알고 있어도 많은 UI를 만들 수 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

⁢</android.support.constraint.ConstraintLayout>


속성의 의미를 알아보겠습니다.

  • app:layout_constraintLeft_toLeftOf=''parent

: 내 View(여기서는 TextView)의 왼쪽을 부모View의 왼쪽에 붙인다.


끝!


오늘 말하고 싶은 포스팅은 이게 전부 입니다.

저 속성들을 이용해서 하나하나 배치 하다 보면 ConstraintLayout을 사용 하고 있는 자기 자신을 발견할 수 있을 겁니다.


몇가지 예시

app:layout_constraintLeft_toRightOf="@id/anotherView"
: 내 View의 왼쪽을 @id/anotherView 오른쪽에 붙인다.

app:layout_constraintRight_toLeftOf="@id/anotherView"
내 View의 오른쪽을 @id/anotherView 왼쪽에 붙인다.

app:layout_constraintTop_toBottomOf="@id/anotherView"
내 View의 위를 @id/anotherView 아래에 붙인다.

app:layout_constraintBottom_toTopOf="@id/anotherView"
내 View의 아래를 @id/anotherView 위에 붙인다.

이런식으로 만들고자 하는 UI를 만들 수 있습니다.


하나만 더 알고 넘어가죠! 위 속성을 예로 설명 하겠습니다.

ConstrainLayout을 사용 하다보면 알겠지만 margin를 사용할 때 주의 사항 입니다.

margin은 anotherView에서 사용 하는게 아니라 내 View에서 사용해야 됩니다.

다른 Layout 에서는 margin을 사용 하고 싶은 곳에서 사용 하면 좌우로 위아래 어느 방향이던 적용이 되었던 반면

ConstrainLayout에서는 margin으로 인해 직접 영향 받는 뷰에 설정을 해야 됩니다.

말이 어려운거지 margin을 여기저거 적용 하다보면 바로 느낌 오실 겁니다.