Injectview (Roboguice) does not work with multiple layouts

So I have different layouts for this one action.

And I have different classes, each of which is open and does its job with the layout.

I embed these classes in Activity via @Inject. All this without any problems.

But when I try to use @InjectView on one of the controls that are in the inactive layout, I get an error.

11-02 19: 17: 31.086: ERROR / AndroidRuntime (1326): called: java.lang.NullPointerException: cannot enter a null value in the be.baes.notes.View.EditNoteImpl.saveButton class when the field is not @Nullable

Then it will be a code.

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

However, I can do it.

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

Is there a better way to do this?

+8
android roboguice
source share
1 answer

I just started using roboguice so that someone with more experience could give a better answer, but this is what I have found so far:

  • In roboguice-1.1.2 (current stable release), @InjectView elements are only introduced when setContentView() is called for the first time in an Activity. Since your code calls setContentView() dynamically from the helper classes, the elements you enter there will not be entered correctly.

  • In roboguice-2.0b2 (current beta), there is support for multiple calls to setContentView() , and your code should work. However, the introduced views are still tied to the Activity context (instead of the declaring class), so each @InjectView can also be @Nullable for all helper classes sharing the same activity.

Since the problem here seems to be embedded in the multiple layout (and therefore multiple setContentView() calls) in one action, one alternative way to do what you want is to avoid this:

  • Instead of multiple layouts, use one layout using the <include/> to load all layouts into the parent 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> 
  • then instead of calling setContentView() use a method that will switch the visible layout in the Activity, something like this:
 // 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); } } 

The above alternative should work for both stable and beta roboguice versions. The trade-off here is that we load multiple layouts at once, rather than loading each several times. It seems to work well enough for me (although it may be different for your needs).

It should be noted that the current page "Upgrading from RoboGuice 1.1 to 2.0" states the following:

The ability to use @InjectView in views (although you need to call RoboGuice.injectMembers () yourself, since there is no RoboView base class and probably never will).

It seems like this should allow you to implement your helper classes, which should be obtained from the view, and make @InjectView work better in them (I hope you do not need them to be @Nullable , since they are less tied to Activity). However, looking at the current code, this function has not yet been implemented (although I could look at the wrong place).

+4
source share

All Articles