-
Notifications
You must be signed in to change notification settings - Fork 0
[Chore] 웹 뷰 안정성 추가 #399
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
[Chore] 웹 뷰 안정성 추가 #399
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,34 +1,49 @@ | ||||||||||||||||||||||||
| package com.eatssu.android.presentation.mypage.terms | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| import android.os.Bundle | ||||||||||||||||||||||||
| import android.webkit.RenderProcessGoneDetail | ||||||||||||||||||||||||
| import android.webkit.WebView | ||||||||||||||||||||||||
| import android.webkit.WebViewClient | ||||||||||||||||||||||||
| import com.eatssu.android.databinding.ActivityWebviewBinding | ||||||||||||||||||||||||
| import com.eatssu.android.presentation.base.BaseActivity | ||||||||||||||||||||||||
| import com.eatssu.common.EventLogger | ||||||||||||||||||||||||
| import com.eatssu.common.enums.ScreenId | ||||||||||||||||||||||||
| import timber.log.Timber | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| class WebViewActivity : | ||||||||||||||||||||||||
| BaseActivity<ActivityWebviewBinding>( | ||||||||||||||||||||||||
| ActivityWebviewBinding::inflate, | ||||||||||||||||||||||||
| ScreenId.EXTERNAL_INQUIRE // shouldLogScreenId가 false라 미사용 | ||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| private var URL = "" | ||||||||||||||||||||||||
| private var TITLE = "" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| override fun onCreate(savedInstanceState: Bundle?) { | ||||||||||||||||||||||||
| super.onCreate(savedInstanceState) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| binding.webview.apply { | ||||||||||||||||||||||||
| webViewClient = WebViewClient() | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // localStorage 사용 시 | ||||||||||||||||||||||||
| // webView.settings.domStorageEnabled = true | ||||||||||||||||||||||||
| webViewClient = object : WebViewClient() { | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // 렌더러 충돌 시 호출되는 콜백 (Android 8.0 이상) | ||||||||||||||||||||||||
| override fun onRenderProcessGone( | ||||||||||||||||||||||||
| view: WebView?, | ||||||||||||||||||||||||
| detail: RenderProcessGoneDetail | ||||||||||||||||||||||||
| ): Boolean { | ||||||||||||||||||||||||
| Timber.e("⚠WebView renderer crashed! Did renderer die: ${detail.didCrash()}") | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // view가 null이거나 이미 죽은 상태이므로 안전하게 정리 | ||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||
| view?.destroy() | ||||||||||||||||||||||||
| } catch (e: Exception) { | ||||||||||||||||||||||||
| Timber.e(e, "Error while destroying crashed WebView") | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // WebView를 재생성하거나 오류 안내 UI를 표시 | ||||||||||||||||||||||||
| recreate() // Activity 재시작으로 복구 | ||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||
| return true // 앱 강제 종료 방지 | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // 웹 페이지에서 새 창을 열 수 있도록 설정 | ||||||||||||||||||||||||
| // Notion 페이지 = DOM Storage(domStorageEnabled) 없으면 동작 불가 | ||||||||||||||||||||||||
|
|
@@ -69,5 +84,14 @@ class WebViewActivity : | |||||||||||||||||||||||
| Timber.d("WebViewActivity screen view logging: $screenId") | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| override fun onDestroy() { | ||||||||||||||||||||||||
| binding.webview.apply { | ||||||||||||||||||||||||
| stopLoading() | ||||||||||||||||||||||||
| webChromeClient = null | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
| webChromeClient = null | |
| webChromeClient = null | |
| webViewClient = null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
메모리 누수를 방지하기 위해 onDestroy에서 WebView 리소스를 해제하는 것은 매우 좋은 방법입니다. webChromeClient를 null로 설정하는 것과 마찬가지로, onCreate에서 설정한 webViewClient도 null로 설정하여 액티비티에 대한 참조를 안전하게 제거하는 것이 좋습니다. 이렇게 하면 익명 클래스로 생성된 WebViewClient가 액티비티의 컨텍스트를 계속 붙잡고 있는 것을 방지할 수 있습니다.
| binding.webview.apply { | |
| stopLoading() | |
| webChromeClient = null | |
| destroy() | |
| } | |
| binding.webview.apply { | |
| stopLoading() | |
| webViewClient = null | |
| webChromeClient = null | |
| destroy() | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling
recreate()inonRenderProcessGonemay cause infinite crash loops if the WebView consistently fails to render. Consider implementing a retry counter or showing an error message instead of automatically recreating the activity.