2

GWT2.5.0を使用しています

私の意図は、ParentBeanオブジェクトにバインドするエディター階層を作成することでした。には、ParentBeanが含まれList<Group>GroupBeanにはとが含まList<ChildBean>れますList<Group>。私が見つけたエディターのチュートリアルから、サブエディターの1つとしてListEditorを含むエディターを作成するのは簡単に思えました。ただし、親エディターがサブListEditorを適切に初期化することはないようです。

これが私がこれをどのように試みたかの説明です。

以下のコードから、ParentBeanEditor他の1つのエディターで構成されるを作成しましたGroupListEditor。実装し
ます。 次に、にはサブエディタとが含まれます。GroupListEditorIsEditor<ListEditor<Group, GroupEditor>>
GroupEditorGroupListEditorChildBeanEditor

オブジェクトのリストを含むをで初期化しParentBeanEditorましたが、どのオブジェクトに対しても構築されていません。メソッドにブレークポイントを設定して、のそれぞれに対してsが作成されていることを確認しましたが、ブレークポイントに到達することはありませんでした(ListEditorはエディターを構築していませんでした)。ParentBeanGroupGroupEditorGroup
EditorSource<GroupEditor>.create(int)GroupEditorGroupParentBean

GroupListEditorのサブエディターであるため、が初期化されることを期待していましたParentBeanEditor。リストもエディターチェーンもに設定されていませんGroupListEditor。サブエディタのリストを拡張して、GroupListEditor直接に設定してみました。これを行うと、前述のブレークポイントに到達し、エディターチェーンにをアタッチしようとしました。しかし、エディターチェーンが設定されることはなく、 95行目にNPEがスローされます。ParentBeanEditorValueAwareEditor<ParentBean>GroupListEditorGroupEditorListEditorWrapper

GroupListEditorこれは、が期待どおりに初期化されていない例です。は設定されないため、 95行EditorChain目にNPEがスローされます。ListEditorWrapper

データ・モデル

public interface ParentBean {
    ...
    List<Group> getGroups();
}

public interface Group {
    ...
    List<ChildBean> getChildBeans();
    List<Group> getGroups();
}

public interface ChildBean {
    // ChildType is an enum
    ChildType getChildType();
}

編集者

ParentBeanエディター

public class ParentBeanEditor extends Composite implements ValueAwareEditor<ParentBean> {

    interface ParentBeanEditorUiBinder extends UiBinder<Widget, ParentBeanEditor> {
    }

    private static ParentBeanEditorUiBinder BINDER = GWT.create(ParentBeanEditorUiBinder.class);

    @Path("groups")
    @UiField
    GroupListEditor groupsEditor;

    public ParentBeanEditor() {
        initWidget(BINDER.createAndBindUi(this));
    }

    @Override
    public void setDelegate(EditorDelegate<ParentBean> delegate) {}

    @Override
    public void flush() {}

    @Override
    public void onPropertyChange(String... paths) {}

    @Override
    public void setValue(ParentBean value) {

        groupsEditor.asEditor().setValue(value.getGroups());
    }
}

GroupListEditor

public class GroupListEditor extends Composite implements IsEditor<ListEditor<Group, GroupEditor>>{

    interface GroupListEditorUiBinder extends UiBinder<VerticalLayoutContainer, TemplateGroupListEditor> {
    }

    private static GroupListEditorUiBinder BINDER = GWT.create(GroupListEditorUiBinder.class);

    private class GroupEditorSource extends EditorSource<GroupEditor> {

        private final GroupListEditor GroupListEditor;

        public GroupEditorSource(GroupListEditor GroupListEditor) {
            this.GroupListEditor = GroupListEditor;
        }

        @Override
        public GroupEditor create(int index) {
            GroupEditor subEditor = new GroupEditor();
            GroupListEditor.getGroupsContainer().insert(subEditor, index);
            return subEditor;
        }

        @Override
        public void dispose(GroupEditor subEditor){
            subEditor.removeFromParent();
        }

        @Override
        public void setIndex(GroupEditor editor, int index){
            GroupListEditor.getGroupsContainer().insert(editor, index);
        }

    }

    private final ListEditor<Group, GroupEditor> editor = ListEditor.of(new GroupEditorSource(this));

    @UiField
    VerticalLayoutContainer groupsContainer;

    public GroupListEditor() {
       initWidget(BINDER.createAndBindUi(this));
    }

    public InsertResizeContainer getGroupsContainer() {
        return groupsContainer;
    }

    @Override
    public ListEditor<Group, GroupEditor> asEditor() {
        return editor;
    }
}

GroupEditor

public class GroupEditor extends Composite implements ValueAwareEditor<Group> {

    interface GroupEditorUiBinder extends UiBinder<Widget, GroupEditor> {}

    private static GroupEditorUiBinder BINDER = GWT.create(GroupEditorUiBinder.class);

    @Ignore
    @UiField
    FieldSet groupField;

    @UiField
    @Path("childBeans")
    ChildBeanListEditor childBeansEditor;

    @UiField
    @Path("groups")
    GroupListEditor groupsEditor;

    public GroupEditor() {
        initWidget(BINDER.createAndBindUi(this));
    }

    @Override
    public void setDelegate(EditorDelegate<Group> delegate) {}

    @Override
    public void flush() { }

    @Override
    public void onPropertyChange(String... paths) {}

    @Override
    public void setValue(Group value) {
        // When the value is set, update the FieldSet header text
        groupField.setHeadingText(value.getLabel());
        groupsEditor.asEditor().setValue(value.getGroups());
        childBeansEditor.asEditor().setValue(value.getChildBeans());
    }
}

ここでChildBeanListEditor言及されているポリモーフィックエディターの方法論を使用します。列挙型の値に基づいて、特定のleafeditorがエディターチェーンに接続されていることを意味しますChildBean.getType()GroupListEditorただし、を適切に初期化することができないため、そのコードは表示していません。

4

1 に答える 1

0

コードに関する 2 つの懸念事項:

ParentBeanEditor.setValue子にデータをフィードするのはなぜですか? このことから、これは がデータを取得していないという事実を回避する方法であったことGroupListEditorがわかります。これは必要ではなく、時間になる前にサブエディターを配線することで NPE を引き起こしている可能性があります。

次に、これを仮定すると、GroupListEditorデータまたはチェーンを取得していないことがわかります。これらの欠如は、エディタ フレームワークがそれを認識していないことを示唆しています。基本的な配線はすべて正しいように見えますが、次の 1 つの点を除きます。EditorDriver はどこにありますか?

起動するだけでエディター フレームワークを使用しようとparentBeanEditor.setValueしていて、ドライバーがない場合は、このツールの主要な機能のほとんどが失われています。ツリー全体で独自の setValue メソッドを呼び出すのではなく、この作業をドライバーに依頼できる必要があります。

簡単なテスト - コンパイルできないような方法で何かを壊してみてください。これには、@Path注釈を のようなものに変更し@Path("doesnt.exist")、アプリを実行しようとすることが含まれます。そのようなパスがないため、再バインド エラーが発生するはずです。これが得られない場合は、間違いなくドライバーを作成して使用する必要があります。

まず、ドライバー自体を試してください。

コードからは、使用しているモデルの種類が明確ではないため、 でSimpleBeanEditorDriver十分であると想定します。もう 1 つの主なオプションは ですがRequestFactoryEditorDriver、実際には を使用する必要はありませんRequestFactoryEditorDriver。リクエストファクトリー。

ドライバーは、編集する予定の Bean タイプと、それを担当するエディター タイプの 2 つの点で一般的です。これらの汎用引数を使用して両方のオブジェクトをトラバースし、データのバインドに必要なコードを生成します。あなたのものはおそらく次のようになります:

public interface Driver extends 
        SimpleBeanEditorDriver<ParentBean, ParentBeanEditor> { }

これらをインターフェイスと同じように宣言しUiBinderます - コード ジェネレーターが周りを見回して重要なものを接続できるようにするのに十分な詳細です。型ができたので、インスタンスを作成します。これはビューで作成される場合がありますが、一部のプレゼンター ロジックによって所有および制御されている場合があります。これはuibinder とは異なることに注意してください。各インスタンスは特定のエディター インスタンスに直接接続されているため、静的インスタンスを保持することはできません

ここで 2 つの手順 - ドライバーを作成し、それを特定のエディター インスタンス (および自動化されるすべてのサブエディター) に初期化します。

ParentBeanEditor editor = ...;
Driver driver = GWT.create(Driver.class);
driver.initialize(editor);

次に、データをドライバーに渡してバインドします。サブオブジェクトを各サブエディターの setValue メソッドに渡し、ListEditor が必要とするエディター チェーンを接続するのはドライバーの役割です。

driver.edit(parentInstance);

これで、アプリケーションの要件が機能するため、ユーザーはオブジェクトを表示または編集できます。編集が完了すると (たとえば、[保存] ボタンをクリックすると)、エディターからのすべての変更をインスタンスにフラッシュできます (また、同じドライバー インスタンスを使用し、その特定のエディター インスタンスを保持していることに注意してください)。

ParentBean instance = driver.flush();

driver.flush()以前の参照を呼び出して再利用することもできたことに注意してくださいparentInstance- それは同じことです。

これまでのところすべてが理にかなっていると仮定すると、実行できるクリーンアップがいくつかあります。ParentBeanEditor は実際には ValueAwareEditor メソッドを使用していないため、削除できます。

public class ParentBeanEditor extends Composite implements Editor<ParentBean> {

    interface ParentBeanEditorUiBinder extends UiBinder<Widget, ParentBeanEditor> {
    }

    private static ParentBeanEditorUiBinder BINDER = GWT.create(ParentBeanEditorUiBinder.class);

    @Path("groups")
    @UiField
    GroupListEditor groupsEditor;

    public ParentBeanEditor() {
        initWidget(BINDER.createAndBindUi(this));
    }
}

まだ実装しているEditor<ParentBean>ことに注意してください。これにより、ドライバーのジェネリックが意味をなすようになり、それ自体が配線されるサブエディターである可能性のあるフィールドがあることが宣言されます。また、@Pathここでの注釈は不要であることがわかります。プロパティと同じ名前のフィールド/メソッド ( getGroups()/ setGroups()==> groups) またはプロパティの名前に「Editor」を加えたもの ( groupsEditor)。エディターに、エディターであるが Bean のプロパティにマップされていないフィールドが含まれている場合、エラーが発生します。実際にこれを意図的に行った場合 (たとえば、データ入力ではなく検索用のテキスト ボックス)、 でタグ付けできます@Ignore

于 2012-12-06T23:52:21.120 に答える