Injectview(Roboguice)不使用多种布局

时间:2011-11-02 18:39:24

标签: android roboguice

所以我对这个活动有不同的布局。

我有不同的课程,每个课程都打开并用布局做事。

我通过@Inject在Activity中注入这些类。这一切都没有问题。

但是当我尝试在非活动布局中的一个控件上使用@InjectView时,我收到错误。

  

11-02 19:17:31.086:ERROR / AndroidRuntime(1326):引起:   java.lang.NullPointerException:无法将null值注入类中   当字段不是@Nullable时,be.baes.notes.View.EditNoteImpl.saveButton

这就是代码。

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

有更好的方法吗?

1 个答案:

答案 0 :(得分:4)

我刚刚开始使用roboguice,所以其他有经验的人可能会给出更好的答案,但这是我到目前为止所发现的:

  • 在roboguice-1.1.2(当前稳定版本)中,@InjectView项仅在活动中第一次调用setContentView()时注入。由于您的代码从辅助类动态调用setContentView(),因此注入的项目将无法正确注入。

  • 在roboguice-2.0b2(当前的测试版)中,支持多个setContentView()调用,您的代码应该可以运行。但是,注入的视图仍然与上下文活动(而不是声明类)相关联,因此在共享相同活动的所有辅助类中,每个@InjectView可能也需要@Nullable

    < / LI>

由于此处的问题似乎植根于单个Activity中的多个布局(因此多个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(),而是使用一种方法来切换Activity上的可见布局,如下所示:
// 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基础   上课,可能永远不会。)

这似乎应该允许您实现从View派生的辅助类,并使其中的@InjectView更好地工作(希望它们不需要@Nullable,因为它们与活动)。但是,看看当前的代码,这个功能似乎还没有实现(虽然我本来可以看错了地方)。