IT_Programming/Android_Java

[안드로이드] 웹뷰(WebView) 멈춤 현상

JJun ™ 2014. 3. 28. 13:34



 출처: http://todvy.tistory.com/tag/TransactionTooLargeException




[현상]

-- 안드로이드 버전 : 킷켓

-- 액티비티 -> 액티비티 -> 프레그먼트(웹뷰)

-- 프레그먼트에서 뒤로가기 시 최초 액티비티로 돌아가게 설계됨

-- 뒤로가기, 재진입 반복

-- 웹뷰 멈춤 현상이 발생



화면 터치 할때마 아래 로그가 찍힌다.

03-27 15:03:06.798     180-3518/? E/BufferQueue﹕ [] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count

03-27 15:02:38.708    5362-5362/ E/Surface﹕ dequeueBuffer failed (Invalid argument)

03-27 15:02:38.708    5362-5362/ E/ViewRootImpl﹕ Could not lock surface

    java.lang.IllegalArgumentException

            at android.view.Surface.nativeLockCanvas(Native Method)

            at android.view.Surface.lockCanvas(Surface.java:243)

            at android.view.ViewRootImpl.drawSoftware(ViewRootImpl.java:2435)

            at android.view.ViewRootImpl.draw(ViewRootImpl.java:2409)

            at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2253)

            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1883)

            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)

            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670)

            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)

            at android.view.Choreographer.doCallbacks(Choreographer.java:574)

            at android.view.Choreographer.doFrame(Choreographer.java:544)

            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)

            at android.os.Handler.handleCallback(Handler.java:733)

            at android.os.Handler.dispatchMessage(Handler.java:95)

            at android.os.Looper.loop(Looper.java:136)

            at android.app.ActivityThread.main(ActivityThread.java:5017)

            at java.lang.reflect.Method.invokeNative(Native Method)

            at java.lang.reflect.Method.invoke(Method.java:515)

            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)

            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)

            at dalvik.system.NativeStart.main(Native Method)



여기서 계속 사용하게 되면 아래와 같이 TransactionTooLargeException으로 앱이 죽는다.

03-27 15:06:02.958    5362-5362/ E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: , PID: 5362
    java.lang.RuntimeException: Adding window failed
            at android.view.ViewRootImpl.setView(ViewRootImpl.java:513)
            at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:259)
            at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
            at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2852)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2250)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: android.os.TransactionTooLargeException
            at android.os.BinderProxy.transact(Native Method)
            at android.view.IWindowSession$Stub$Proxy.addToDisplay(IWindowSession.java:683)
            at android.view.ViewRootImpl.setView(ViewRootImpl.java:502)
            at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:259)
            at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
            at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2852)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2250)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)



스택 오버플로 검색 결과

http://stackoverflow.com/questions/20554621/after-a-while-of-usage-my-app-freezes-during-scrolling-a-webview-saying-could


<스택 오버플로우 해결 방법>

-- onPause 일때 webview destroy

-- onResume 일때 다시 생성


<문제>

-- 스크롤 유지 안됨

-- 갱신이 필요없는경우(화면 꺼짐, 홈버튼 이동)에도 종료와 생성이 일어남(깜박거림 현상)



위 방법 적용시 문제가 해결된다.. 하지만 몇가지 문제로 사용할 수 없다.


여기서 내 앱의 구조를 보면


1. 지금 앱의 구조는 프레그먼트안에 웹뷰가 있는 형태임

2. 프레그먼트 onDetach시 웹뷰 destroy 코드가 들어가 있음. 


안드로이드 life cycle에서 종료된 activity의 onDestory는 새로운 액티비티가 onResume까지 진행될때 불린다 


여기서 새로운 웹뷰가 로드되는 동안 구 웹뷰가 destroy 이 되는 상황이 발생한다

킷캣에서 이부분이 문제가 됐다는 결론을 내렸다.


그래서.


당황하지 않고 액티비티가 finsh 되는 상황에서 불리는 onStop일때 웹뷰 destory 코드를 넣으면 끝.

@Override

    public void onStop() {

        super.onStop();

        if (getActivity().isFinishing()) {

           // 여기에 웹뷰 destroy 코드를 넣었음..

        }

    } 


아직 같은 문제가 재현되지 않는걸로 봐서는 해결된것 같다. 끝.