8

したがって、この1つのアクティビティにはさまざまなレイアウトがあります。

そして、私はそれぞれが開いてレイアウトでそれぞれのことを行うさまざまなクラスを持っています。

これらのクラスを@Injectを介してアクティビティに注入します。これはすべて問題ありません。

しかし、アクティブでないレイアウトにあるコントロールの1つで@InjectViewを使用しようとすると、エラーが発生します。

11-02 19:17:31.086:エラー/ AndroidRuntime(1326):原因:java.lang.NullPointerException:フィールドが@Nullableでない場合、クラスbe.baes.notes.View.EditNoteImpl.saveButtonにnull値を挿入できません

これがコードになります。

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

これを行うためのより良い方法はありますか?

4

1 に答える 1

4

私はroboguiceを使い始めたばかりなので、経験豊富な人がより良い答えを出すことができるかもしれませんが、これは私がこれまでに見つけたものです:

  • roboguice-1.1.2(現在の安定版リリース)では、アクティビティで最初に呼び出された@InjectViewときにのみアイテムが注入されます。setContentView()コードはsetContentView()補助クラスから動的に呼び出すため、そこに挿入されたアイテムは正しく挿入されません。

  • roboguice-2.0b2(現在のベータ版)では、複数のsetContentView()呼び出しがサポートされており、コードは機能するはずです。ただし、挿入されたビューは(クラスを宣言するのではなく)コンテキストActivityに関連付けられているため、同じ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);
    }
}

上記の代替手段は、安定版とベータ版の両方のroboguiceリリースで機能するはずです。ここでのトレードオフは、複数の異なる時間に各レイアウトをロードするのではなく、同時に複数のレイアウトをロードすることです。それは私にとっては十分に機能しているようです(ただし、ニーズによっては異なる場合があります)。

私が注意しなければならないことの1つは、現在の「RoboGuice 1.1から2.0へのアップグレード」ページで、次のことが言及されていることです。

ビューで@InjectViewを使用する機能(ただし、RoboView基本クラスがなく、おそらくそうなることはないため、RoboGuice.injectMembers()を自分で呼び出す必要があります)。

これにより、Viewから派生する補助クラスを実装し@InjectView、それらをより適切に機能させることができるようになります(@Nullableアクティビティとの関連性が低いため、補助クラスを実装する必要がないことを願っています)。ただし、現在のコードを見ると、この機能はまだ実装されていないようです(間違った場所を見ていた可能性はありますが)。

于 2011-11-08T22:01:14.207 に答える