2015-04-22 6 views
60

Używam paska narzędzi jako paska akcji w działaniu. Próbuję dodać metodę getActionBar().setDisplayHomeAsUpEnabled(true); do pliku Activity.java, aby uzyskać nawigację w górę dla starszych urządzeń.Sposób naprawy Metoda getActionBar może generować java.lang.NullPointerException

Metoda generuje następujący komunikat o błędzie w Android Studio:

wywołania metody mogą produkować java.lang.NullPointerException

Nawigacja w górę na pasku narzędzi działa dobrze na nowszych urządzeniach ... teraz próbuję dowiedzieć się, jak upewnić się, że będzie działać na starszych urządzeniach. Proszę doradzić.

Od build.gradle:

dependencies { 
    compile "com.android.support:appcompat-v7:22.1.0" 
} 

Od AndroidManifest.xml:

android:theme="@style/Theme.AppCompat.NoActionBar.FullScreen" 

Od styles.xml

<style name="Theme.AppCompat.NoActionBar.FullScreen" parent="AppTheme"> 
<item name="android:windowNoTitle">true</item> 
<item name="windowActionBar">false</item> 
<item name="android:windowFullscreen">true</item> 

z Activity.java

public class CardViewActivity extends AppCompatActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.cardviewinput); 

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 

    if (toolbar != null) { 
     // Up navigation to the parent activity for 4.0 and earlier 
     getActionBar().setDisplayHomeAsUpEnabled(true); 
     toolbar.setNavigationIcon(R.drawable.ic_action_previous_item); 
     toolbar.setNavigationOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       onBackPressed(); 
      } 
     }); 
    } 

} 
+1

nie jest twój motyw, który nie ma ActionBar? – juunas

Odpowiedz

102

Faktycznie Android Studio nie pokazuje ci "komunikat o błędzie" , to tylko ostrzeżenie.

Niektóre odpowiedzi proponują użycie asercji, środowisko wykonawcze Dalvik ma domyślnie wyłączone assertion, więc trzeba je włączyć, aby faktycznie coś zrobił. W tym przypadku (asercja jest wyłączona), to co robisz, to tylko oszukiwanie Androida Studio, aby nie wyświetlać ostrzeżenia. Ponadto wolę nie używać "assert" w kodzie produkcyjnym.

Moim zdaniem to, co powinieneś zrobić, jest bardzo proste.

if(getActionBar() != null){ 
    getActionBar().setDisplayHomeAsUpEnabled(true); 
} 

Aktualizacja: W przypadku używasz wersji biblioteki wsparcie na pasku działań, należy wymienić getActionBar() z getSupportActionBar().

if(getSupportActionBar() != null){ 
    getSupportActionBar().setDisplayHomeAsUpEnabled(true); 
} 
+2

Chociaż początkowo używałem aserta do "rozwiązania" ostrzeżenia, zgadzam się, że zalecany kod jest lepszy niż assert hack. Odpowiedź została przegłosowana i zaakceptowana. Zauważ, że używam AppCompatActivity jako klasy, więc muszę użyć metody getSupportActionBar() w moim rozwiązaniu, a nie funkcji getActionBar(), którą pokazałeś powyżej. – AJW

+2

Dlaczego Android Studio nie daje tego samego ostrzeżenia dla innych metod, takich jak getSupportActionBar(). SetTitle()? –

+0

Używam getSupportActionBar()! = Null, ale wciąż jestem rzucony zerowy wskaźnik na moim pasku narzędzi. Czy ktoś wie, co się dzieje? Próbowałem linii assert, która również po prostu rzuca zerowy wskaźnik! ??! Co się dzieje!??!?!?! – ZooMagic

33

Po pierwsze, musisz ustawić pasek narzędzi jako wsparcie ActionBar. Następnie, jeśli masz pewność, że będzie tam cały czas, po prostu zaznacz to jako! = Null. To powie kompilatorowi, że nie będzie to wartość NULL, więc test zerowy przechodzi.

@Override 
protected void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.cardviewinput); 

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 

    assert getSupportActionBar() != null; 
    getSupportActionBar().setDisplayHomeAsUpEnabled(true); // it's getSupportActionBar() if you're using AppCompatActivity, not getActionBar() 
} 
+0

OK, wygląda dobrze, ale linia assert generuje błąd "Can not resolve symbol" getSupportActionBar "" w Android Studio. Czy powinien to być "getSupportActionBar()"? Proszę doradzić. – AJW

+0

Dostęp do getSupportActionBar można uzyskać tylko po rozszerzeniu AppCompatActivity lub FragmentActivity – Sheychan

8

Dziękuję Ci Andrew za odpowiedź. Jeśli masz szufladę Nav lub coś innego, co używa getSupportActionBar(), musisz dodać assert getSupportActionBar()! = Null;

Peace,

Przykład:

@Override 
public void setTitle(CharSequence title) { 
    mTitle = title; 
    assert getSupportActionBar() != null; 
    getSupportActionBar().setTitle(mTitle); 
} 
+3

. Czy jest to ważne do celów produkcyjnych lub tylko do testów? – gian1200

+0

gian1200 Nie jestem pewien. Dobre pytanie. Planowałem wkrótce wydać moją aplikację, więc będę przeprowadzał badania, zanim wydam tę wersję ... Thx. – Scott

+0

Domyślam się, że kompilator zmieni go na coś takiego: "jeśli jest zerowy, a następnie wyślij assertExeption"; nie pozwala ci obsłużyć błędu. – gian1200

4

Spróbuj tego:

private ActionBar getActionBar() { 
    return ((AppCompatActivity) getActivity()).getSupportActionBar(); 
} 
2

dodać assert getSupportActionBar() != null; przed getSupportActionBar().setDisplayHomeAsUpEnabled(true);

3

Co mam zrobić jest zastąpić metodę w moim podstawowej działalności getSupportActionBar() i dodać @NonNull adnotacji. W ten sposób otrzymuję tylko jedno ostrzeżenie o lintach w podstawowej aktywności o tym, jak używam adnotacji @NonNull dla czegoś, co ma adnotację @Nullable.

@NonNull 
    @Override 
    public ActionBar getSupportActionBar() { 
     // Small hack here so that Lint does not warn me in every single activity about null 
     // action bar 
     return super.getSupportActionBar(); 
    } 
+0

dzięki za odpowiedź. Nie wiem, jak używać lint. Czy możesz wypowiedzieć się na temat jakiejkolwiek przewagi, jaką ma twoja odpowiedź na pytanie Adama Ghaniego powyżej? – AJW

+0

Przy podejściu Adama musisz napisać instrukcję if we wszystkich swoich działaniach. Z moim podejściem musisz po prostu zastąpić getSupportActionBar w podstawowej aktywności, a reszta kodu pozostaje taka, jak poprzednio. –

1

I stworzył ogólną klasę takich jak:

public final class Cast 
{ 
    private Cast() {} 

    /** 
    * Helps to eliminate annoying NullPointerException lint warning. 
    */ 
    @android.support.annotation.NonNull 
    public static <T> T neverNull(T value) 
    { 
     return value; 
    } 
} 

potem mogę wykorzystać go w dowolnym rozmowy z ostrzeżeniem NullPointerException dla których jestem pewien, że to nigdy nie nastąpi, na przykład

final ActionBar actionBar = Cast.neverNull(getSupportActionBar()); 
actionBar.setDisplayHomeAsUpEnabled(true); 
actionBar.setHomeButtonEnabled(true); 

P.S. nie zapomnij dodać "com.android.support:support-annotations" do pliku gradle.

0
if(actionBar != null) { 
    actionBar.setHomeButtonEnabled(true); 
    actionBar.setBackgroundDrawable(ContextCompat.getDrawable(mContext, 
            R.drawable.action_bar_gradient)); 
} 
0

wykorzystanie tego motywu: android:theme="@style/Theme.AppCompat.Light.NoActionBar"

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
toolbar.setTitle("Title"); 
setSupportActionBar(toolbar); 
ActionBar actionBar = getSupportActionBar(); 
actionBar.setHomeButtonEnabled(true); 
actionBar.setHomeAsUpIndicator(R.drawable.ic_action_previous_item); 
actionBar.setDisplayHomeAsUpEnabled(true);