2016-07-01 20 views
3

Ich überprüfte den Android-Quellcode und fand die folgende Methode. (core/java/android/view/WindowManagerGlobal.java)Wann denkt Android, dass ein Fenster verloren gegangen ist?

Es scheint, dass, wenn who != null das Fenster/View verloren ist. Kann mir jemand erklären, was dahinter steckt?

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); 
       } 
      } 
     } 
    } 

Antwort

3

ich die Quelle überprüft ... Ich bin darüber nicht ganz sicher, aber sie geht mein Verständnis ...

"den" Argument Aktivitätsnamen nur

Checking closeAll() Aufrufen von Methoden, können Sie sehen, dass who ist nur der Name der Aktivitätsklasse, die zerstört wurde und ein Fenster zurückgelassen:

WindowManagerGlobal.getInstance().closeAll(wtoken, 
         r.activity.getClass().getName(), "Activity"); 

Closealle() aufgerufen wird, wenn durchgesickert aufgetreten

Es scheint, dass WindowManagerGlobal.closeAll() aufgerufen wird, wenn das Windows bereits ausgelaufen ist. Also, who != null es ist nur ein Haken, um sicherzustellen, dass String nicht NULL ist.

Wenn nicht null, wird WindowLeaked erstellt und das Protokoll gedruckt. WindowLeaked ist eine Klasse, die AndroidRuntimeException

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

Am wichtigsten ist die Tatsache, dass, wenn sich WindowManagerGlobal.closeAll() genannt wird, bedeutet dies, dass die Windows bereits ausgelaufen ist.

CloseAll() Aufruf der Methode

In View.java, können wir sehen, dass WindowManagerGlobal.closeAll() aufgerufen wird, wenn ein leacked erkannt wird:

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"); 
    } 

Im Code oben können wir sehen, dass WindowManagerGlobal.closeAll() ausgelöst wird, wenn eine Inkonsistenz gefunden wird:

  1. wtoken != nullwtoken zeigt, dass View eine mAttachInfo.mWindowToken Informationen. Mit anderen Worten, es wird immer noch von einem Fenster gehalten.
  2. r.mPendingRemoveWindow == null Es gibt keine ausstehende Ansicht, die entfernt werden soll.

Also ist es inkonsistent. Eine Ansicht ist angefügt (hat noch eine mAttachInfo), aber ich habe bereits alle ausstehenden Fenster entfernt (mPendingRemoveWindow ist Null) ... Also, diese Ansicht ist durchgesickert.

hoffe, ich konnte Ihnen helfen, Grüße

REF:

WindowManagerGlobal

ActivityThread

View

+0

Große Antwort! Vielen Dank! Eine weitere Frage: Ich habe bemerkt, dass 'closeAll()' dreimal aufgerufen wird (zweimal in 'handleDestroyActivity' und einmal in' cleanUpPendingRemoveWindows', kann ein Fensterleck in den beiden anderen Fällen auftreten? – JackWM