Fascination
article thumbnail

프로젝트를 하다보니 로그아웃 그리고 회원탈퇴를 한 후,

앱을 처음 실행하는 로그인 액티비티로 이동하고 싶어졌다

 

내 프로젝트의 각 액티비티와 프래그먼트를 대충 설명해보자면,,,

MainActivity: homefragment, likefragment, userfragment가 띄워짐

userfragment: firebase에서 현재 로그인된 user의 정보(닉네임, 이메일)를 받아오며

정보 수정으로 이동하는 버튼, 로그아웃 버튼, 회원 탈퇴 버튼이 있음

주제와 관련된 요소들은 위에가 끝일 것 같다

 

처음에 구현한 코드는 이러했다

//탈퇴 버튼
btnDrop.setOnClickListener {

	mFirebaseAuth!!.currentUser!!.delete()
	mDatabaseRef.removeValue()

	val intent = Intent(getActivity(), LoginActivity::class.java)
	startActivity(intent)
            
}

 

하지만 아래 사진과 같은 오류를 만나버렸다,,

NullPointerException

보통 안드로이드 스튜디오에서 NullPointerException이 발생하는 경우는

받아오는 값이 null일 때 많이 발생했다

extension을 통해 그냥 xml에서 정의했던 id를 바로쓸 때 다른 xml의 id를 쓴다던가

오타를 내는 경우에 가장 많이 봤던 오류다

(그래서 findviewbyid를 사용하는 습관을 들였다)

하지만 이번에는 그런 부분은 잘 확인했기 때문에 프래그먼트의 생명주기를 생각해보게 되었다

 

우선 생활코딩에 글을 올렸었는데 위와 같은 답변을 받을 수 있었다

그래서 Log로 데베에서 정보를 불러오는 homefragment와 userfragment에 

화면이 눈앞에서 사라진 후의 생명주기에 각각 로그를 달아보았다

onDestroyView -> onDestory -> onDetach 

순으로 이어지길래 각각 로그를 달아 확인해보았다

 

homefragment에서 userfragment로 이동한 후

탈퇴버튼을 눌렀을 때의 로그이다

userfragment로 이동했을 때 위와같은 로그가 찍힌 후

탈퇴 버튼을 누르니 NullPointerException이 발생했다

 

예상으로는 MainActivity가 살아있고 사라지지 않은 요소들에서

데이터베이스를 통해 정보를 가져오는 부분이 있어서라고 생각했다

 

우선 생활코딩에서 알려주신대로 EventListener를 remove하는 코드를

각 프래그먼트에 넣어주었다

 override fun onDestroy() {
        super.onDestroy()
        mDatabaseRef.removeEventListener(listener)
        Log.e("UserFragment", "유저프래그먼트 파괴됨")
}

위와 같이 remove해주었다

 

그리고 내 예상처럼 MainActivity가 없어져야 할 것 같아

fragment에서 MainActivity를 지우는 방법을 생각했다

 btnDrop.setOnClickListener {

            mDatabaseRef.removeEventListener(listener)
            Log.e("UserFragment", "listner remove")
            mDatabaseRef.removeValue()
            mFirebaseAuth!!.currentUser!!.delete()
            getActivity()?.finishAffinity()
            Log.e("userFragment","전체액티비티파괴")
            val intent = Intent(getActivity(), LoginActivity:class.java)
            startActivity(intent)

 }

회원탈퇴버튼을 눌렀을 때 fragment에서 우선 EventListener를 해제해주고

(전체 액티비티를 파괴할 때 같이 되겠거니 예상했지만 로그에

유저 프래그먼트에 달았던 로그들이 안떠서 추가해주었다)

realtime database에서 값을 지우고

인증에서 가입된 회원을 지운 후

전체 액티비티를 파괴하는 코드를 써보았다

그리고 LoginActivity로 이동하게 나머지 코드는 그대로 두었다

 

but,, 전에 액티비티 파괴후 파괴했다고 생각했던 HomeFragment가 여전히 문제였다

그래서 intent부터 문제가 있다고 생각했고 잘 생각해보니 getActivity()는

userfragment가 프래그먼트이므로, 결론적으로 프래그먼트를 실행하는

MainActivity를 다시 얻어오는게 아닌가 싶었다

그래서 생각을 바꿔 앱을 다시 실행하게 만드는게 좋을 것 같다는 결론을 내렸다

흐름상 앱을 실행하면 바로 나오는 액티비티가 LoginActivity이기 때문이다

 

//탈퇴 버튼
btnDrop.setOnClickListener {

	mDatabaseRef.removeEventListener(listener)	
	Log.e("UserFragment", "listner remove")
	mDatabaseRef.removeValue()
	mFirebaseAuth!!.currentUser!!.delete()
	getActivity()?.finishAffinity()
	val packageManager = requireContext().packageManager
	val intent = packageManager.getLaunchIntentForPackage(requireContext().packageName)
	val componentName = intent!!.component
	val mainIntent = Intent.makeRestartActivityTask(componentName)
	requireContext().startActivity(mainIntent)
	Runtime.getRuntime().exit(0)

}

위와 같이 메인액티비티 파괴 후 앱을 새로 실행해보았다

 

homefragment에서 userfragment로 이동한 후

탈퇴버튼을 다시 눌렀을 때의 로그이다

에러가 발생하지 않고 화면도 Login화면으로 잘 뜨는 것을 확인할 수 있었다

 

오류해결 성공..!!

 

기본적으로 로그는 error로그로 설정하고 error 필터링 건 후에 확인하는게 제일 편한 것 같다

이렇게 intent 관련하여 얻어가는게 생겼다 ㅎㅎ..

 

 

 


[참고]

 

 

[Android] app restart 앱 재실행

1 2 3 4 5 6 7 8 private void restart(Context context) {     PackageManager packageManager = context.getPackageManager();     Intent intent = packageManager.getLaunchIntentForPackag..

yoon-0506.tistory.com

앱 재실행하는 코드는 위의 분의 티스토리를 참고하여 코틀린 코드로 변환해 사용했다 !

profile

Fascination

@euna-319

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!