2011-11-02 4 views
8

Quindi ho diversi layout per questa attività.Injectview (Roboguice) non funziona con più layout

E ho classi diverse che aprono ciascuna e fanno le loro cose con un layout.

Iniettare queste classi nell'attività tramite @Inject. Tutto questo è senza problemi.

Ma quando provo a utilizzare @InjectView su uno dei controlli presenti nel layout non attivo, viene visualizzato un errore.

11-02 19: 17: 31,086: ERROR/AndroidRuntime (1326): causato da: java.lang.NullPointerException: impossibile iniettare valore nullo in classe be.baes.notes.View.EditNoteImpl .saveButton quando campo non è @Nullable

Questo sarebbe quindi il codice.

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

Posso comunque farlo.

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

C'è un modo migliore per farlo?

+0

C'è un motivo per cui rendere Button @Nullable non è un'opzione? –

+0

L'ho provato, ma non mi ha iniettato il pulsante. – chrissie1

+0

Stai usando RoboGuice 2.0? Questo * può * funzionare in 2.0 – emmby

risposta

4

ho appena iniziato ad utilizzare roboguice modo che qualcun altro con più esperienza potrebbe essere in grado di dare una risposta migliore, ma questo è quello che ho trovato finora:

  • In roboguice-1.1.2 (la attuale versione stabile), gli articoli @InjectView vengono iniettati solo quando setContentView() viene chiamato la prima volta nell'attività. Dato che il codice chiama setContentView() in modo dinamico dalle classi ausiliarie, gli elementi inseriti non verranno iniettati correttamente.

  • In roboguice-2.0b2 (la versione beta corrente), è disponibile il supporto per più chiamate setContentView() e il codice dovrebbe funzionare. Tuttavia, le visualizzazioni iniettate sono ancora legate all'attività di contesto (anziché alla classe di dichiarazione), quindi ogni @InjectView dovrà anche essere @Nullable in tutte le classi ausiliarie che condividono la stessa attività.

Dal momento che il problema qui sembra essere radicata nel layout multipla (e quindi più setContentView() chiamate) in una singola attività, un modo alternativo di fare quello che vuoi è quello di evitarlo come segue:

  • Invece di avere diversi layout, utilizzare un unico layout utilizzando il tag <include/> per caricare tutti i layout in un FrameLayout genitore:
<?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> 
  • allora, invece di chiamare setContentView(), utilizzare un metodo che si alternerà il layout visibile sull'attività, qualcosa di simile:
// 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); 
    } 
} 

È possibile che questo alternativa dovrebbe funzionare per entrambe le versioni stable e beta roboguice. Il compromesso qui è che stiamo caricando diversi layout contemporaneamente anziché caricarli in momenti diversi. Sembra funzionare abbastanza bene per me (anche se potrebbe essere diverso per le tue esigenze).

Una cosa che vorrei sottolineare è che sulla corrente "Upgrading from RoboGuice 1.1 to 2.0" pagina, è menzionato il seguente:

La possibilità di utilizzare @InjectView in Vista (anche se avrete bisogno di chiamare RoboGuice.injectMembers() te stesso, dal momento che non esiste una classe RoboView e probabilmente non lo sarà mai).

Sembra che questo dovrebbe consentire di implementare le vostre classi ausiliarie che saranno ricavati dalla vista e rendere @InjectView in loro funzionano meglio (si spera senza bisogno di loro di essere @Nullable dal momento che sono meno legati al Attività). Tuttavia, guardando il codice corrente, questa funzione non sembra essere ancora implementata (anche se avrei potuto guardare nel posto sbagliato).