2013-04-24 15 views
62

Devo usare un oggetto OnGlobalLayoutListener e quindi rimuovere il listener, ho avuto un problema con i metodi deprecati che risolvo con il seguente codice.OnGlobalLayoutListener: deprecazione e compatibilità

protected void onCreate(Bundle savedInstanceState) { 
    final LinearLayout llTotal = (LinearLayout) findViewById(R.id.mmc_ll); 
    ViewTreeObserver vto = llTotal.getViewTreeObserver(); 
    if(vto.isAlive()){ 
     vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
      @Override 
      public void onGlobalLayout() { 
       // 
       // mycode 
       // 
       if (Build.VERSION.SDK_INT<16) { 
        removeLayoutListenerPre16(llTotal.getViewTreeObserver(),this); 
       } else { 
        removeLayoutListenerPost16(llTotal.getViewTreeObserver(), this); 
       } 
      } 
     }); 
    } 
    super.onCreate(savedInstanceState); 
} 

@SuppressWarnings("deprecation") 
private void removeLayoutListenerPre16(ViewTreeObserver observer, OnGlobalLayoutListener listener){ 
    observer.removeGlobalOnLayoutListener(listener); 
} 

@TargetApi(16) 
private void removeLayoutListenerPost16(ViewTreeObserver observer, OnGlobalLayoutListener listener){ 
    observer.removeOnGlobalLayoutListener(listener); 
} 

E 'corretto? C'è un modo migliore per gestire la compatibilità?

L'esecuzione del codice dell'emulatore con API 10 ho il seguente avviso in LogCat

04-24 09:30:12.565: I/dalvikvm(471): Could not find method android.view.ViewTreeObserver.removeOnGlobalLayoutListener, referenced from method com.my.project.ActivityHome.removeLayoutListenerPost16 
04-24 09:30:12.565: W/dalvikvm(471): VFY: unable to resolve virtual method 2950: Landroid/view/ViewTreeObserver;.removeOnGlobalLayoutListener (Landroid/view/ViewTreeObserver$OnGlobalLayoutListener;)V 

Posso ignorarli del devo risolvere in qualche modo?

risposta

126

Sto usando questo nel mio progetto:

@TargetApi(Build.VERSION_CODES.JELLY_BEAN) 
public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener listener){ 
    if (Build.VERSION.SDK_INT < 16) { 
     v.getViewTreeObserver().removeGlobalOnLayoutListener(listener); 
    } else { 
     v.getViewTreeObserver().removeOnGlobalLayoutListener(listener); 
    } 
} 

sembra simile al tuo. Testato su diversi dispositivi (4.2.2 & 2.3.3) e funziona perfettamente. sembra che sia l'unico modo .... Se trovi qualcos'altro, mi piacerebbe saperlo. buona fortuna

+0

All'inizio ho usato il codice, ma danno un errore (chiamata richiede livello di API 16 (corrente min è 8): android.view.ViewTreeObserver # removeOnGlobalLayoutListener) e un avvertimento (Il metodo removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener) dal tipo ViewTreeObserver è deprecato). Il mio codice risolve questi problemi ma fornisce l'avviso di LogCat – crbin1

+0

, l'avviso va bene. è perché stai usando jar di qualche versione di sdk con funzione deprecata per i dispositivi

+9

@ crbin1 è possibile aggiungere @TargetApi (Build.VERSION_CODES.JELLY_BEAN) prima della dichiarazione della funzione, se si desidera evitare di visualizzare questo avviso/errore. –

9

Certo che controllare la versione di Android e chiamare il metodo corretto è molto più prudente, ma se si dà un'occhiata al codice sorgente di Android è possibile vedere qualcosa di interessante:

@Deprecated 
    public void removeGlobalOnLayoutListener(OnGlobalLayoutListener victim) { 
     removeOnGlobalLayoutListener(victim); 
    } 

Questo codice è stata ritagliata da API 18

36

credo che il modo corretto utilizza Build.VERSION.SDK_INT e Build.VERSION_CODES:

public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener listener){ 
     if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 
       v.getViewTreeObserver().removeGlobalOnLayoutListener(listener); 
      } else { 
       v.getViewTreeObserver().removeOnGlobalLayoutListener(listener); 
      } 
} 
+1

Penso che tu voglia passare il listener a 'removeGlobalLayoutListener' invece di' this' –

3

Secondo il docs:

Questo metodo è sconsigliata a livello API 16. Uso #removeOnGlobalLayoutListener invece

funziona come un fascino.

7
mView.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
     @Override 
     public void onGlobalLayout() { 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 
       mView.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
      } else { 
       //noinspection deprecation 
       mView.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
      } 
      // 
      // mycode 
      // 
     } 
    });