2011-11-02 11 views
8

Mam różne układy dla tej jednej aktywności.Injectview (Roboguice) nie działa z wieloma układami

Mam różne klasy, które otwierają się i robią swoje rzeczy z układem.

Wstrzykuję te zajęcia do Aktywności przez @Inject. Wszystko to bez problemu.

Ale kiedy próbuję użyć @InjectView na jednym z elementów sterujących, które są w nieaktywnym układzie, pojawia się błąd.

11-02 19: 17: 31,086: błąd/Android Runtime (1326) spowodowane przez: java.lang.NullPointerException: Nie można wprowadzić wartość zerową do klasy be.baes.notes.View.EditNoteImpl .saveButton, gdy pole nie jest @Nullable

To byłby kod.

public class EditNoteImpl implements EditNote { 
    @Inject CancelEditNoteClickListener cancelEditNoteClickListener; 
    @Inject SaveNoteClickListener saveNoteClickListener; 
    @Inject Provider<Activity> activity; 
    @InjectView(R.id.saveButton) Button saveButton; 

    /* (non-Javadoc) 
    * @see be.baes.notes.EditNote#activateEditNote() 
    */ 
    @Override 
    public void activateEditNote() 
    { 
     activity.get().setContentView(R.layout.editnote); 

     this.saveButton.setOnClickListener(saveNoteClickListener); 
    } 
} 

Mogę jednak to zrobić.

public class EditNoteImpl implements EditNote { 
    @Inject CancelEditNoteClickListener cancelEditNoteClickListener; 
    @Inject SaveNoteClickListener saveNoteClickListener; 
    @Inject Provider<Activity> activity; 
    private Button saveButton; 

    /* (non-Javadoc) 
    * @see be.baes.notes.EditNote#activateEditNote() 
    */ 
    @Override 
    public void activateEditNote() 
    { 
     activity.get().setContentView(R.layout.editnote); 
     saveButton = (Button)activity.get().findViewById(R.id.saveButton); 

     this.saveButton.setOnClickListener(saveNoteClickListener); 
    } 
} 

Czy jest lepszy sposób to zrobić?

+0

Czy jest jakiś powód, dla którego przycisk @Nullable nie jest dostępny? –

+0

Próbowałem, ale to nie wstrzykuje również przycisku. – chrissie1

+0

Czy używasz RoboGuice 2.0? To * może * działa w 2.0 – emmby

Odpowiedz

4

Właśnie zaczął używać roboguice więc ktoś z większym doświadczeniem może być w stanie dać lepszą odpowiedź, ale to co znalazłem do tej pory:

  • W roboguice-1.1.2 (the aktualne stabilne wydanie), @InjectView przedmioty są wstrzykiwane tylko wtedy, gdy setContentView() jest wywoływana po raz pierwszy w Aktywności. Ponieważ Twój kod wywołuje setContentView() dynamicznie z klas pomocniczych, wstrzyknięte elementy nie zostaną prawidłowo wstrzyknięte.

  • W roboguice-2.0b2 (obecna wersja beta) istnieje obsługa wielu połączeń setContentView(), a kod powinien działać. Widoki wstrzykiwane są jednak nadal powiązane z kontekstem Activity (zamiast z deklarowaną klasą), więc każdy @InjectView będzie musiał również być @Nullable dla wszystkich klas pomocniczych dzielących tę samą Aktywność.

Ponieważ chodzi tu wydaje się być zakorzenione w stwardnieniu układ (i stąd wiele setContentView() przychodzące) w jednej aktywności, jeden alternatywny sposób zrobić to, co chcesz, aby uniknąć go następująco:

  • Zamiast kilku układów, korzystać z jednego układu za pomocą znacznika <include/> załadować wszystkie układy w FrameLayout dominującej:
<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" > 

    <include layout="@layout/layout1" /> 

    <include layout="@layout/layout2" /> 

    <!-- other layouts... --> 

</FrameLayout> 
  • następnie, zamiast dzwonić setContentView(), należy użyć metody, która będzie przełączać widoczną układ z działalności, coś takiego:
// instead of: activity.setContentView(R.layout.layout1); 
// use: activity.showLayout(R.id.layoutview1); 
public void showLayout(int layoutViewId) { 
    final View view = findViewById(layoutViewId); 
    final ViewGroup root = (ViewGroup) view.getParent(); 
    for (int i = 0; i < root.getChildCount(); i++) { 
     final View v = root.getChildAt(i); 
     v.setVisibility(v == view ? View.VISIBLE : View.GONE); 
    } 
} 

Powyższa alternatywa powinna pracować dla zarówno wersje stabilne, jak i beta roboguice. Kompromisem tutaj jest ładowanie kilku układów w tym samym czasie zamiast ładowania każdego z nich w kilku różnych czasach. Wydaje się, że działa to wystarczająco dobrze dla mnie (chociaż może być inne dla twoich potrzeb).

Jedno muszę zauważyć, że na obecnym "Upgrading from RoboGuice 1.1 to 2.0" stronie, co następuje wymienić:

Możliwość korzystania @InjectView w widokach (choć trzeba zadzwonić RoboGuice.injectMembers() siebie, ponieważ nie ma klasy RoboView i prawdopodobnie nigdy nie będzie).

Wydaje się, że powinno to pozwalają wdrożyć zajęcia pomocnicze mają zostać uzyskane z widokiem i uczynić @InjectView w nich działać lepiej (oby nie trzeba dla nich być @Nullable ponieważ są one mniej przywiązany do aktywności). Jednak patrząc na obecny kod, ta funkcja nie wydaje się być jeszcze zaimplementowana (chociaż mogłem szukać w niewłaściwym miejscu).

Powiązane problemy