android - Injectview(Roboguice)不适用于多种布局

标签 android roboguice

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

我有不同的类,每个类都打开并使用布局做他们的事情。

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

但是当我尝试在非 Activity 布局中的控件之一上使用@InjectView 时,我收到错误消息。

11-02 19:17:31.086: ERROR/AndroidRuntime(1326): Caused by: java.lang.NullPointerException: Can't inject null value into class be.baes.notes.View.EditNoteImpl.saveButton when field is not @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);
    }
}

有更好的方法吗?

最佳答案

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

  • 在 roboguice-1.1.2(当前稳定版本)中,@InjectView只有在 setContentView() 时才会注入(inject)项目在 Activity 中被第一次调用。由于您的代码调用 setContentView()动态地从辅助类中注入(inject)的项目将不会被正确注入(inject)。

  • 在 roboguice-2.0b2(当前测试版)中,支持多个 setContentView()电话和你的代码应该工作。然而,注入(inject)的 View 仍然绑定(bind)到上下文 Activity (而不是声明类)所以每个 @InjectView可能还需要 @Nullable所有辅助类共享同一个 Activity。

由于这里的问题似乎根源于单个 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);
    }
}

上述替代方案应该适用于稳定版和测试版 roboguice 版本。这里的权衡是我们同时加载多个布局,而不是在几个不同的时间加载每个布局。它似乎对我来说效果很好(尽管它可能会因您的需求而有所不同)。

我应该注意的一件事是,在当前 "Upgrading from RoboGuice 1.1 to 2.0"页面,提到以下内容:

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

看起来这应该允许您实现从 View 派生的辅助类并生成 @InjectView在它们中工作得更好(希望它们不需要是 @Nullable 因为它们与 Activity 的联系较少)。然而,从目前的代码来看,这个功能似乎还没有实现(虽然我可能看错了地方)。

关于android - Injectview(Roboguice)不适用于多种布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7985615/

相关文章:

android - 什么更消耗我的电池? wifi、数据连接 (3g) 或 GPS。安卓

android - 使用 Phonegap/Cordova 相机插件从相机或图库中选择照片

android - 我应该在我的 Android 应用程序中使用什么数据库方法

android - 让 Mockito 与 RoboGuice 和 Robolectric 一起工作

android - Roboguice 2.0 @Inject 单例到 POJO

java - OnClickListener 在 startActivity 上抛出 NullPointerException

android - 测试 Activity 并通过额外?

java - .class 和 .dex 文件有什么区别?

java - 如何在 android 适配器中使用 Roboguice 依赖注入(inject)

java - 在 HttpURLConnection 中设置 setChunkedStreamingMode 向服务器发送数据失败