반응형

이번 포스팅은 StringBuffer 와 StringBuilder 에 대하여 알아보도록 하겠습니다.

Java에서 문자열 사용시 String 객체를 많이 사용하는데 String 객체는 new String() 함수를 통해 객체를 매번 생성하여 메모리적으로 좋지 않다는 걸 알고 계실 것입니다. 그래서 저는 StringBuffer 객체를 많이 사용하는데 Android Build 시 StringBuild를 사용할는 Lint 내용을 보고 의문이 들어 두 객체를 비교하여 보겠습니다.

StringBuilder와 StringBuffer를 비교합니다.
이 두 클래스는 서로 거의 동일합니다. 동일한 결과를 반환하는 동일한 이름의 메소드를 사용합니다. 하지만 두 가지 주요 차이점이 있습니다.

Thread Safety

- StringBuffer 메서드가 동기화되므로 한 번에 하나의 Thread에서만 StringBuffer 인스턴스의 메서드를 호출할 수 있습니다. 반면 StringBuilder 메서드는 동기화되지 않으므로 여러  Thread가 차단되지 않고 StringBuilder 클래스의 메서드를 호출할 수 있습니다.

그래서 우리는 StringBuffer가  Thread Safety 클래스인 반면 StringBuilder는 그렇지 않다는 결론을 내렸습니다.

▶ Speed

- StringBuffer는 실제로 StringBuilder보다 2~3배 느립니다. 그 이유는 StringBuffer의 동기화 때문입니다. 한 번에 하나의 개체에서 하나의 Thread만 실행되도록 허용하면 StringBuilder보다 코드 실행 속도가 훨씬 느려집니다.

사실 두 객체가 거의 동일한 메소드와 기능을 수행하기 때문에 아무거나 사용하여도 무방하지만 저는 속도면에서 조금 더 빠른 StringBuilder 클래스를 더 많이 사용합니다.

반응형

'Development > Java' 카테고리의 다른 글

[Java] Java Class 파일 DeCompile  (0) 2020.04.08
[Java] Handler 정리  (0) 2019.09.05
[Java] System.arraycopy 사용법  (0) 2019.09.04
반응형

이번 포스팅은 App Architecture 가이드 두 번째 포스팅입니다.

예제를 통해 좀 더 자세히 알아보도록 하겠습니다.


사용자 인터페이스 시작

UI는 fragment UserProfileFragment와 관련 레이아웃 파일 user_profile_layout.xml로 구성됩니다.

UI를 만들려면 데이터 모델에 다음 데이터 요소가 있어야 합니다.

▶ 사용자 ID: 사용자의 식별자입니다. fragment 인수를 사용하여 이 정보를 fragment에 전달하는 것이 좋습니다. Android OS에서 프로세스를 제거해도 이 정보가 유지되므로, 앱을 다시 시작할 때 ID를 사용할 수 있습니다.

▶ 사용자 개체: 사용자에 관한 세부정보를 보유하는 데이터 클래스입니다.

이 정보를 유지하기 위해 ViewModel 아키텍처 구성요소를 기반으로 하는 UserProfileViewModel을 사용합니다.

ViewModel 개체는 fragment나 activity 같은 특정 UI 구성요소에 대한 데이터를 제공하고 Model과 커뮤니케이션하기 위한 데이터 처리 비즈니스 로직을 포함합니다. 예를 들어 ViewModel은 데이터를 로드하기 위해 다른 구성요소를 호출하고 사용자 요청을 전달하여 데이터를 수정할 수 있습니다. ViewModel은 UI 구성요소에 관해 알지 못하므로 구성 변경(예: 기기 회전 시 activity 재생성)의 영향을 받지 않습니다.

지금까지 다음 파일을 정의했습니다.

▶ user_profile.xml: 화면의 UI 레이아웃 정의

▶ UserProfileFragment: 데이터를 표시하는 UI 컨트롤러

▶ UserProfileViewModelUserProfileFragment에서 볼 수 있도록 데이터를 준비하고 사용자 상호작용에 반응하는 클래스

다음 소스 코드는 이러한 파일의 시작 콘텐츠를 보여줍니다. 

편의를 위해 레이아웃 파일은 생략합니다.

UserProfileViewModel

class UserProfileViewModel:ViewModel(){

val userId :String= TODO() val user :User= TODO() }

UserProfileFragment

class UserProfileFragment:Fragment(){

override fun onCreateView(inflater:LayoutInflater, container:ViewGroup?, savedInstanceState:Bundle?):View{
return inflater.inflate(R.layout.main_fragment, container,false)
}
}

user를 가져오려면 ViewModel에서 Fragment 인수에 액세스해야 합니다. Fragment에서 인수를 전달할 수도 있고, 더 나은 방법으로 SavedState 모듈을 사용해 ViewModel에서 직접 인수를 읽을 수 있습니다.

참고: SavedStateHandle을 사용하면 ViewModel에서 관련 Fragment 또는 Activity의 저장된 상태와 인수에 액세스할 수 있습니다.


// UserProfileViewModel

class UserProfileViewModel( savedStateHandle:SavedStateHandle ):ViewModel(){
val userId :String= savedStateHandle["uid"]?: throwIllegalArgumentException("missing user id") val user :User= TODO()
}

// UserProfileFragment
privateval viewModel:UserProfileViewModel by viewModels(factoryProducer ={SavedStateVMFactory(this)}        ... )

이제 user 개체가 확보되면 Fragment에 알려야 합니다. 여기에서 LiveData 아키텍처 구성요소가 사용됩니다.

LiveData는 식별 가능한 데이터 홀더입니다. 앱의 다른 구성요소에서는 이 홀더를 사용하여 상호 간에 명시적이고 엄격한 종속성 경로를 만들지 않고도 개체 변경사항을 모니터링할 수 있습니다. 또한 LiveData 구성요소는 activity, fragment, 서비스와 같은 앱 구성요소의 수명 주기 상태를 고려하고, 개체 유출과 과도한 메모리 소비를 방지하기 위한 정리 로직을 포함합니다.

참고: RxJava와 같은 라이브러리를 이미 사용하고 있다면 LiveData 대신 계속 사용해도 됩니다. 그러나 이러한 라이브러리와 방법을 사용하는 경우 앱의 수명 주기를 올바르게 처리해야 합니다. 특히 관련 LifecycleOwner가 중지되면 데이터 스트림이 일시중지되고, 관련 LifecycleOwner가 제거되면 이러한 스트림이 제거되도록 해야 합니다. android.arch.lifecycle:reactivestreams 아티팩트를 추가하여 LiveData를 다른 반응형 스트림 라이브러리(예: RxJava2)와 함께 사용할 수도 있습니다.

LiveData 구성요소를 앱에 통합하기 위해 UserProfileViewModel의 필드 유형을 LiveData<User>로 변경합니다. 이제 데이터가 업데이트되면 UserProfileFragment에 정보가 전달됩니다. 또한 이 LiveData 필드는 수명 주기를 인식하기 때문에 더 이상 필요하지 않은 참조를 자동으로 정리합니다.

UserProfileViewModel

class UserProfileViewModel( savedStateHandle:SavedStateHandle):ViewModel(){

val userId :String= savedStateHandle["uid"]?: throw IllegalArgumentException("missing user id") val user :LiveData<User>= TODO()
}

이제 데이터를 관찰하고 UI를 업데이트하도록 UserProfileFragment를 수정합니다.

UserProfileFragment

override fun onViewCreated(view:View, savedInstanceState:Bundle?){ super.onViewCreated(view, savedInstanceState)
viewModel
.user.observe(viewLifecycleOwner){ // update UI } }

사용자 프로필 데이터가 업데이트될 때마다 onChanged() 콜백이 호출되고 UI가 새로고침됩니다.

반응형
반응형

이번 포스팅은 Android Build 오류에 대하여 알아보도록 하겠습니다.


< Error>

A SQLiteConnection object for database '+data+user+0+com_example_android+databases+example_db' was leaked!  Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.



< Solution > 

이 Build 오류의 원인은 example.db 라는 데이터베이스를 연결하여 사용을 하는데 연결 후 정상적으로 transaction이 종료가 되지 않았다는 뜻입니다. 다시 말해 메모리 상에 database 객체가 있지만 이 객체가 정상적으로 close 가 되지 않은 상태에서 로직이 진행이 되었다는 뜻입니다.


해결방법으로는 데이터베이스 연결을 한 후 일련의 작업이 끝난 후 데이터베이스를 제대로 종료를 해주면 됩니다.

db = DBHelper.getWritableDatabase(); 로 선언한 변수가 있다고 가정하여 아래와 같이 close()를 해주면 됩니다.

public void close() {

    db.close();

}

반응형

+ Recent posts