Injectview(Roboguice)不使用多个布局多个、布局、Injectview、Roboguice

2023-09-05 03:25:48 作者:Agoni、暮念

所以,我有不同的布局为这一个活动。

和我有不同的类,每个打开的,做自己的事情了布局。

我通过@注入的活动注入这些类。所有这一切都没有问题。

但是,当我尝试使用@InjectView上处于不活跃布局控件之一,我得到一个错误。

  

11-02 19:17:31.086:ERROR / AndroidRuntime(1326):产生的原因:   显示java.lang.NullPointerException:不能注入空值成class   be.baes.notes.View.EditNoteImpl.saveButton当字段不@Nullable

这随后将是code。

 公共类EditNoteImpl实现EditNote {
    @注入CancelEditNoteClickListener cancelEditNoteClickListener;
    @注入SaveNoteClickListener saveNoteClickListener;
    @注入提供商LT;活动>活动;
    @InjectView(R.id.saveButton)按钮saveButton;

    / *(非Javadoc中)
     * @see be.baes.notes.EditNote#activateEditNote()
     * /
    @覆盖
    公共无效activateEditNote()
    {
        activity.get()的setContentView(R.layout.editnote)。

        this.saveButton.setOnClickListener(saveNoteClickListener);
    }
}
 
C winform中如何将泛型集合对象的多个外键对象的值绑定到dataGridView控件上去

我可以然而做到这一点。

 公共类EditNoteImpl实现EditNote {
    @注入CancelEditNoteClickListener cancelEditNoteClickListener;
    @注入SaveNoteClickListener saveNoteClickListener;
    @注入提供商LT;活动>活动;
    私人按钮saveButton;

    / *(非Javadoc中)
     * @see be.baes.notes.EditNote#activateEditNote()
     * /
    @覆盖
    公共无效activateEditNote()
    {
        activity.get()的setContentView(R.layout.editnote)。
        saveButton =(按钮)activity.get()findViewById(R.id.saveButton)。

        this.saveButton.setOnClickListener(saveNoteClickListener);
    }
}
 

是否有这样做的更好的办法?

解决方案

我刚开始使用roboguice让别人有更多的经验,或许能给出更好的答案,但是这是我发现迄今:

在roboguice-1.1.2(当前稳定版本), @InjectView 项目注入仅在的setContentView()被称为首次活动。由于您的code调用的setContentView()动态地从辅助类,注入的项目将不会有正确的注入。

在roboguice-2.0b2(当前的测试版),有多种支持的setContentView()来电和code应该工作。然而,注入的观点仍然依赖于上下文活动(而不是声明类),所以每个 @InjectView 将有可能还需要 @Nullable 所有辅助类共享相同的活动。

由于这里的问题似乎根植于多个布局(因此多个的setContentView()电话)的一个活动,一种选择的方式做你想要什么是为了避免如下:

包括/> 而不是有几个布局,使用&LT使用单个布局标记加载的所有布局到父的FrameLayout:

 < XML版本=1.0编码=UTF-8&GT?;
<的FrameLayout的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =FILL_PARENT
    机器人:layout_height =FILL_PARENT>

    <包括布局=@布局/布局1/>

    <包括布局=@布局/布局2/>

    <! - 其他布局...  - >

< /的FrameLayout>
 

然后,而不是调用的setContentView(),使用将切换可见版面上的活动的方法,是这样的: 而不是

  //:activity.setContentView(R.layout.layout1);
//使用方法:activity.showLayout(R.id.layoutview1);
公共无效showLayout(INT layoutViewId){
    最终的视图中查看= findViewById(layoutViewId);
    最后的ViewGroup根=(ViewGroup中)view.getParent();
    的for(int i = 0; I< root.getChildCount();我++){
        最终的视图V = root.getChildAt(我);
        v.setVisibility(ΔV==观点View.VISIBLE:View.GONE);
    }
}
 

以上的替代应该为稳定和beta roboguice版本。权衡这里是我们加载多个布局,在同一时间,而不是装载每一个在几个不同的时间。它似乎工作不够好,对我来说(虽然它可能是您的需求不同)。

有一件事我要说明的是,在当前升级从RoboGuice 1.1 2.0页,以下提到:

  

使用@InjectView在视图中(虽然你需要调用的能力   RoboGuice.injectMembers()自己,因为没有RoboView基地   类,并可能永远不会)。

看来,这应该让你实现你的辅助类从视图派生,使 @InjectView 在他们更好地工作(希望没有必要对他们来说是 @Nullable ,因为它们不太依赖于活动)。然而,看着目前的code,这个功能似乎并没有被尚未实现(虽然我也一直在寻找在错误的地方)。

So I have different layouts for this one Activity.

And I have different classes that each open and do their thing with a layout.

I inject these classes in the Activity via @Inject. All this is without problem.

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

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

This would then be the 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);
    }
}

I can however do this.

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 of doing this?

解决方案

I have just started to use roboguice so someone else with more experience might be able to give a better answer, but this is what I found so far:

In roboguice-1.1.2 (the current stable release), @InjectView items are injected only when setContentView() is called the first time in the Activity. Since your code calls setContentView() dynamically from the auxiliary classes, the injected items there won't be injected correctly.

In roboguice-2.0b2 (the current beta), there is support for multiple setContentView() calls and your code should work. However, injected views are still tied to the context Activity (instead of the declaring class) so every @InjectView will potentially also need to be @Nullable across all auxiliary classes sharing the same Activity.

Since the issue here seems to be rooted in the multiple layout (and hence multiple setContentView() calls) in a single Activity, one alternative way to do what you want is to avoid it as follow:

Instead of having several layouts, use a single layout using the <include/> tag to load all the layouts into a 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 toggle the visible layout on 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 the stable and beta roboguice releases. The trade-off here is we are loading several layouts at the same time instead of loading each one at several different times. It seems to work well enough for me (though it might be different for your needs).

One thing I should note is that on the current "Upgrading from RoboGuice 1.1 to 2.0" page, the following is mentioned:

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).

It seems that this should allow you to implement your auxiliary classes to be derived from View and make @InjectView in them work better (hopefully no need for them to be @Nullable since they are less tied to the Activity). However, looking at the current code, this feature does not seem to be implemented yet (although I could have been looking at the wrong place).

 
精彩推荐
图片推荐