2011-11-02 69 views
8

所以我對這個Activity有不同的佈局。Injectview(Roboguice)不能使用多個佈局

而且我有不同的課程,每個課程都打開並使用佈局完成自己的任務。

我通過@Inject在活動中注入這些類。這一切都沒有問題。

但是,當我嘗試使用@InjectView在一個非活動佈局的控件之一時出現錯誤。

11-02 19:17:31.086:ERROR/AndroidRuntime(1326): 顯示java.lang.NullPointerException:致不能注入空值成 類be.baes.notes.View.EditNoteImpl .saveButton當字段不爲@Nullable時

這就是代碼。

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

但是我可以這樣做。

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

有沒有更好的方法來做到這一點?

+0

是否有原因使Button @Nullable不是一個選項? –

+0

我試過了,但是也沒有注入按鈕。 – chrissie1

+0

您是否使用RoboGuice 2.0?這*可能*工作在2.0 – emmby

回答

4

我剛開始使用roboguice所以別人更多的經驗或許能給出更好的答案,但是這是我迄今發現:

  • 在roboguice-1.1.2(在當前穩定版本),@InjectView項目僅在setContentView()被稱爲活動中的第一次時才被注入。由於您的代碼動態地從輔助類中調用setContentView(),因此注入的項目將無法正確注入。

  • 在roboguice-2.0b2(目前的測試版)中,支持多個setContentView()調用,並且您的代碼應該可以工作。然而,注入的視圖仍然與上下文Activity(而不是聲明類)相關,所以每個@InjectView可能也需要在共享相同活動的所有輔助類中爲@Nullable

由於這裏的問題似乎根植於多個佈局(並因此多次setContentView()呼叫)在一個單一的活動,一個另類的方式做你想要的是避免如下:

  • 代替具有幾個佈局的,使用一個單一的佈局使用<include/>標籤到所有佈局加載到一個父的FrameLayout:
<?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> 
  • 然後,而不是調用setContentView(),使用將切換上的活動可見佈局的方法,像這樣:
// 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); 
    } 
} 

上述替代方案應該工作穩定版和beta版roboguice發佈。這裏的折衷是我們在同一時間加載多個佈局,而不是在幾個不同的時間加載每個佈局。它對我來說似乎工作得不錯(儘管它可能會因您的需要而不同)。

有一件事我要指出的是,目前"Upgrading from RoboGuice 1.1 to 2.0"頁面上,以下提到:

在視圖中使用@InjectView(雖然你需要調用 RoboGuice.injectMembers的能力()你自己,因爲沒有RoboView基礎,所以可能永遠不會)。

看來,這應該讓你實現從查看派生的輔助類,使@InjectView在他們更好地工作(希望沒有必要對它們進行@Nullable因爲它們較少依賴於活動)。然而,看看當前的代碼,這個功能似乎還沒有實現(儘管我可能一直在看錯的地方)。