2012-03-29 26 views
5

Mỗi hoạt động của tôi cần triển khai chế độ xem đơn lẻ hiệu chỉnh. Chiến lược tốt nhất để đưa chúng vào hoạt động là gì?sử dụng GIN trong các hoạt động GWT

  1. constructor injection constructor Hoạt động được gọi là từ getActivity của một ActivityMapper(). Các ctor đã có một tham số (một đối tượng Place). Tôi sẽ phải tạo ActivityMapper với tất cả các lượt xem có thể được tiêm. Không tốt ...

  2. phương pháp tiêm - "Một chức năng được chú thích được tự động thực thi sau khi hàm tạo đã được thực thi". (GWT trong hành động, 2nd Ed.) Vâng, "sau khi ctor đã được thực thi" rõ ràng là không đủ nhanh bởi vì xem (hoặc một dịch vụ RPC tiêm theo cách này) vẫn chưa được khởi tạo khi phương thức hoạt động của start() được gọi và tôi có được một NPE.

  3. xây dựng bộ phun với GWT.create trong ctor của Activity. Vô dụng, vì họ sẽ không còn là những người độc thân nữa.

Trả lời

7

Điều gì có hiệu quả nhất đối với chúng tôi là sử dụng Assisted Inject.

Tùy thuộc vào từng trường hợp, chúng tôi đã xác định các nhà máy hoạt động trong chính hoạt động đó, trong một gói (để xây dựng tất cả các hoạt động trong gói đó) hoặc trong ActivityMapper.

public class MyActivity extends AbstractActivity { 
    private final MyView view; 

    @Inject 
    MyActivity(MyView view, @Assisted MyPlace place) { 
     this.view = view; 
     ... 
    } 
    ... 
} 

public class MyActivityMapper implements ActivityMapper { 
    public interface Factory { 
    MyActivity my(MyPlace place); 

    FooActivity foo(FooPlace place); 

    ... 
    } 

    // using field injection here, feel free to replace by constructor injection 
    @Inject 
    private Factory factory; 

    @Overrides 
    public Activity getActivity(Place place) { 
     if (place instance MyPlace) { 
     return factory.my((MyPlace) place); 
     } else if (place instance FooPlace) { 
     return factory.foo((FooPlace) place); 
     } 
     ... 
    } 
} 

// in the GinModule: 
install(new GinFactoryModuleBuilder().build(MyActivityMapper.Factory.class)); 

BTW, cho phương pháp tiêm để làm việc, bạn vẫn phải tạo ra các hoạt động của bạn thông qua GIN, vì vậy bạn sẽ có vấn đề tương tự như với constructor injection. Không có phép thuật, GIN sẽ không tiêm ma thuật các lớp mà nó không biết và thậm chí không biết khi nào chúng được khởi tạo. Bạn có thể kích hoạt phun phương pháp một cách rõ ràng bằng cách thêm phương pháp để Ginjector của bạn, nhưng tôi sẽ không khuyên bạn nên nó (mã của bạn sẽ phụ thuộc vào các Ginjector, mà là một cái gì đó bạn nên tránh nếu bạn có thể):

interface MyGinjector extends Ginjector { 
    // This will construct a Foo instance and inject its constructors, fields and methods 
    Foo foo(); 

    // This will inject methods and (non-final) fields of an existing Bar instance 
    void whatever(Bar bar); 
} 

... 

Bar bar = new Bar("some", "arguments"); 
myGinjector.whatever(bar); 
... 

Một cuối cùng từ: Tôi sẽ không chuyển trực tiếp đối tượng địa điểm đến hoạt động. Cố gắng phân tách các địa điểm và hoạt động, cho phép bạn di chuyển mọi thứ (ví dụ: tạo phiên bản di động hoặc máy tính bảng, nơi bạn chuyển đổi giữa chế độ xem chính và chi tiết, thay vì hiển thị chúng cạnh nhau) bằng cách thay đổi bố cục "vỏ" và người lập bản đồ hoạt động. Để thực sự phân tách chúng, bạn phải tạo một số loại hoa tiêu , điều này sẽ trừu tượng các cuộc gọi placeController.goTo() của bạn để các hoạt động của bạn không bao giờ xử lý các địa điểm.

+1

Hi Thomas, Đó chính xác là những gì chúng tôi làm trong ứng dụng của chúng tôi (sử dụng nhà máy) và nó hoạt động tốt. Tuy nhiên, làm cách nào bạn đề xuất tích hợp nó với AsyncProvider của GIN để tách mã? (chúng tôi đang sử dụng ActivityAsyncProxy http://ars-codia.raphaelbauer.com/2011/04/gwt-gin-and-simple-split-points.html) –

2

Theo kinh nghiệm của tôi, thực hành tốt là có người lập bản đồ hoạt động riêng để giải quyết các địa điểm và hoạt động (bản đồ). Trong hoạt động bạn có người dẫn chương trình, đây là ví dụ về một hoạt động:

public class ActivityOne extends AbstractActivity { 

    @Inject 
    private Presenter presenter; 

    @Override 
    public void start(AcceptsOneWidget panel, EventBus eventBus) { 
    presenter.go(panel); 
    } 

} 

Người dẫn chương trình có quan điểm tiêm bên trong, nó được xây dựng (người dẫn chương trình) khi "đi" phương pháp được gọi. Người trình bày được khai báo là singleton trong mô-đun GIN và lượt xem thường là đơn (với một số ngoại lệ như các tiện ích nhỏ xuất hiện ở nhiều nơi).

Ý tưởng là di chuyển liên hệ bằng chế độ xem bên trong người trình bày (vì mục tiêu của người trình bày là xử lý logic và truy xuất/cập nhật dữ liệu đến/từ chế độ xem, theo MVP). Bên trong người dẫn chương trình, bạn sẽ phải cũng là dịch vụ RPC, bạn không cần phải khai báo vì GIN sẽ "kỳ diệu" làm ví dụ cho bạn, bằng cách gọi GWT.create Dưới đây là một ví dụ về một người dẫn chương trình rất đơn giản:

public class PresenterOneImpl implements Presenter { 

     @Inject 
     private MyView view; 


     @Inject 
     private SomeRpcServiceAsync someRpc; 


     @Override 
     public void go(AcceptsOneWidget panel) { 
     view.setPresenter(this); 
     panel.setWidget(view); 
     updateTheViewWithData(); 
     } 
} 

Cuối cùng, tôi phải lưu ý rằng có một số hoạt động, giống như một hoạt động cho trình đơn, xử lý các địa điểm và chế độ xem trực tiếp để hiển thị trạng thái hiện tại. Các hoạt động này được lưu trữ bên trong trình ánh xạ để tránh trường hợp mới mỗi khi địa điểm được thay đổi.

3

Tôi đã chọn một phương pháp hơi khác với tính linh hoạt bạn cần. Tôi không nhớ nơi tôi đã chọn mẫu thiết kế này, nhưng đó không phải là ý tưởng của tôi. Tôi tạo ra các hoạt động như vậy

public class MyActivity extends AbstractActivity{ 

    private MyView view; 
    @Inject static PlaceController pc; 


    @Inject 
    public MyActivity(MyView view) { 
     super(); 
     this.view = view; 
    } 

    public MyActivity withPlace(MyPlace myPlace) { 
     return this; 
    } 
... 
} 

Sau đó, tôi sử dụng này trong mapper hoạt động như thế này:

public class MyMapper implements ActivityMapper { 

    @Inject Provider<MyActivity> myActivityProvider; 

    public Activity getActivity(Place place) { 

     if (place instanceof MyPlace){ 
      return myActivityProvider.get().withPlace(place); 
     } else if 
... 

Ngoài ra hãy chắc chắn View được khai báo singleton trong file mô-đun gin.

Các vấn đề liên quan