2016-07-01 1 views
3

Android 소스 코드를 확인한 결과, 다음과 같은 방법이 있습니다. (core/java/android/view/WindowManagerGlobal.java)안드로이드는 언제 창문 유출을 고려합니까?

who != null 창 /보기가 유출 된 것 같습니다. 아무도 이것 뒤에 무슨 일이 일어날 지 설명 할 수 있습니까?

"는"인수가 활동 이름을 단

검사 인 나는 소스를 확인

public void closeAll(IBinder token, String who, String what) { 
     synchronized (mLock) { 
      int count = mViews.size(); 
      //Log.i("foo", "Closing all windows of " + token); 
      for (int i = 0; i < count; i++) { 
       //Log.i("foo", "@ " + i + " token " + mParams[i].token 
       //  + " view " + mRoots[i].getView()); 
       if (token == null || mParams.get(i).token == token) { 
        ViewRootImpl root = mRoots.get(i); 

        //Log.i("foo", "Force closing " + root); 
        if (who != null) { 
         WindowLeaked leak = new WindowLeaked(
           what + " " + who + " has leaked window " 
           + root.getView() + " that was originally added here"); 
         leak.setStackTrace(root.getLocation().getStackTrace()); 
         Log.e(TAG, "", leak); 
        } 

        removeViewLocked(i, false); 
       } 
      } 
     } 
    } 

답변

3

... 내가 그것에 대해 완전히 확실하지 않다 그러나 그녀는 나의 이해 간다 ... closeAll() 메서드를 호출하면 who이 파괴되어 하나의 창을 남긴 액티비티 클래스 이름임을 알 수 있습니다 :

WindowManagerGlobal.getInstance().closeAll(wtoken, 
         r.activity.getClass().getName(), "Activity"); 
유출 된 경우라고 10

CLOSEALL는() 윈도우가 이미 유출 된 경우 WindowManagerGlobal.closeAll()가 호출 될 것으로 보인다

발생했습니다. 따라서 who != nullStringNULL이 아닌지 확인합니다.

null이 아닌 경우 WindowLeaked이 작성되고 로그가 인쇄됩니다. WindowLeakedAndroidRuntimeException

final class WindowLeaked extends AndroidRuntimeException { 
    public WindowLeaked(String msg) { 
     super(msg); 
    } 
} 

이 가장 중요한 역할을 한 WindowManagerGlobal.closeAll()가 호출되는 경우는 윈도우가 이미 유출 된 것을 의미한다는 사실이다 확장하는 클래스입니다.

CLOSEALL()를 호출하는 방법

View.java에서는 검출되는 leacked 때 WindowManagerGlobal.closeAll() 호출되는 것을 볼 수

ActivityThread.java

private void handleDestroyActivity(IBinder token, boolean finishing, 
            int configChanges, boolean getNonConfigInstance) { 
    ... 
    IBinder wtoken = v.getWindowToken(); 
    ... 
    if (wtoken != null && r.mPendingRemoveWindow == null) { 
     WindowManagerGlobal.getInstance().closeAll(wtoken, 
       r.activity.getClass().getName(), "Activity"); 
    } 

을 코드에서 위의 경우 불일치가 발견되면 WindowManagerGlobal.closeAll()이 실행됨을 알 수 있습니다 :

  1. wtoken != nullwtokenViewmAttachInfo.mWindowToken 정보를 가지고 있음을 보여준다. 다시 말해서, 그것은 어떤 창문에 의해 여전히 열리고 있습니다.
  2. r.mPendingRemoveWindow == null 삭제할 보류중인보기가 없습니다.

그래서 일치하지 않습니다. 하나의보기가 첨부되어 있지만 (아직 mAttachInfo) 아직 대기중인 모든 창을 제거했습니다 (mPendingRemoveWindow은 null입니다 ...). 그래서보기가 유출되었습니다.

희망은 당신 감사

도움이 될 수 REF :

WindowManagerGlobal

ActivityThread

View

+0

멋진 대답! 감사! 'closeAll()'이 세 번 ('handleDestroyActivity'에서 두 번,'cleanUpPendingRemoveWindows'에서 한 번 호출됩니다. 다른 두 가지 경우에 윈도우 누수가 발생할 수 있습니까? – JackWM