2016-10-10 92 views
1

我试图注入一个字段在类中实现的接口类型。匕首2没有注入接口类型

这是我迄今为止所做的。

这些视图interface:

public interface PostView extends View, ListView<Post>, EmptyView<String> { 
} 
public interface View { 

    public void showProgressIndicator(); 

    public void hideProgressIndicator(); 

    public void onSuccess(); 

    public void onFailure(); 

    public void onFailure(String message); 
} 

public interface ListView<E> { 

    public void onListItems(List<E> items, 
      int pageNum, 
      int pageSize, 
      boolean next); 

} 

public interface EmptyView<E> { 

    public void onEmpty(E e); 

    public void onEmpty(String message); 
} 

组件:

@Singleton 
@Component(modules = ApiModule.class) 
public interface ApiComponent { 

    Api provideApi(); 

} 

@UserScope 
@Component(dependencies = ApiComponent.class, modules = PostModule.class) 
public interface PostComponent { 

    PostPresenter providePostPresenter(); 

    void inject(NetworkTest networkTest); 
} 

模块:

@Module 
public class ApiModule { 

    private static final Logger logger = Logger.getLogger(ApiModule.class.getSimpleName()); 

    private final String baseUrl; 

    public ApiModule(String baseUrl) { 
     this.baseUrl = baseUrl; 
    } 

    @Provides 
    @Singleton 
    boolean provideIsLoggerEnabled() { 
     logger.info("proviedIsLoggerEnabled()"); 
     return true; 
    } 

    @Provides 
    @Singleton 
    OkHttpClient provideOkHttpClient(boolean logEnabled) { 
     logger.info(" provideOkHttpClient(logEnabled)"); 
     HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); 
     Interceptor requestInterceptor = new Interceptor() { 
      @Override 
      public Response intercept(Chain chain) throws IOException { 
       return chain.proceed(chain.request()); 
      } 
     }; 
     interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 
     OkHttpClient.Builder builder = new OkHttpClient.Builder() 
       .addInterceptor(requestInterceptor) 
       .addNetworkInterceptor(interceptor); 
     return builder.build(); 
    } 

    @Provides 
    @Singleton 
    Api provideApi(OkHttpClient okHttpClient) { 
     logger.info("provideApi"); 
     Retrofit retrofit = new Retrofit.Builder() 
       .client(okHttpClient) 
       .baseUrl(baseUrl) 
       .addConverterFactory(GsonConverterFactory.create()) 
       .build(); 
     return retrofit.create(Api.class); 
    } 

} 

@Module 
public class PostModule { 

    private static final Logger logger = Logger.getLogger(PostModule.class.getSimpleName()); 
    private final PostView postView; 

    public PostModule(PostView postView) { 
     this.postView = postView; 
    } 

    @Provides 
    @UserScope 
    PostService providePostService(Api api) { 
     logger.info("Provider post with api now"); 
     return new PostService(api); 
    } 

    @Provides 
    @UserScope 
    PostPresenter providePostPresenter(PostService service) { 
     logger.info("Providing presenter with service now"); 
     return new PostPresenter(postView, service); 
    } 
} 

主讲人:

public class PostPresenter extends AbstractPresenter { 

    private static final Logger logger = Logger.getLogger(PostPresenter.class.getSimpleName()); 
    private PostView postView; 
    private PostService postService; 

    public PostPresenter(PostView postView, PostService postService) { 
     this.postView = postView; 
     this.postService = postService; 
    } 

    @Override 
    protected View getView() { 
     logger.info("Getting view"); 
     throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 
    } 

    public void getPosts() { 
     logger.info("Getting posts "); 
     Call<List<Post>> posts = this.postService.getPosts(); 
     postView.showProgressIndicator(); 
     posts.enqueue(new Callback<List<Post>>() { 

      @Override 
      public void onResponse(Call<List<Post>> call, Response<List<Post>> rspns) { 
       postView.onListItems(rspns.body(), 1, 25, true); 
       postView.hideProgressIndicator(); 
       postView.onSuccess(); 
      } 

      @Override 
      public void onFailure(Call<List<Post>> call, Throwable thrwbl) { 
       onApiCallError(thrwbl); 
       postView.hideProgressIndicator(); 
      } 
     }); 
    } 
} 

public abstract class AbstractPresenter { 

    private static final Logger logger = Logger.getLogger(AbstractPresenter.class.getSimpleName()); 

    protected abstract View getView(); 

    /* 
    * General indication whether api call stated or not. 
    */ 
    protected void onApiCallStart() { 
     logger.info("Api call started"); 
     View v = getView(); 
     if (v != null) { 
      v.showProgressIndicator(); 
     } 
    } 

    protected void onApiCallEnd() { 
     logger.info("Api call finished"); 
     View v = getView(); 
     if (v != null) { 
      v.hideProgressIndicator(); 
     } 
    } 

    /* 
    * General error handling 
    */ 
    protected void onApiCallError(Throwable e) { 
     logger.info("Api call terminated with error"); 
     View v = getView(); 
     if (v != null && e != null) { 
      v.onFailure(e.getMessage()); 
     } 
    } 
} 

NetworkTest:

public class NetworkTest implements PostView { 

    private static final Logger logger = Logger.getLogger(NetworkTest.class.getSimpleName()); 

    private PostComponent component; 
    @Inject 
    PostPresenter presenter; 

    public NetworkTest(ApiComponent apiComponent) { 
     component = DaggerPostComponent.builder() 
       .apiComponent(apiComponent) 
       .postModule(new PostModule(this)) 
       .build(); 
    } 

    public void init() { 
     component.inject(this); 
    } 

    void showPosts() { 
     if (presenter != null) { 
      logger.info("Hurray it worked"); 
      presenter.getPosts(); 
     } else { 
      logger.warning("Alas it failed"); 
     } 
    } 

    @Override 
    public void showProgressIndicator() { 
     logger.info("Show progress indicator here"); 
    } 

    @Override 
    public void hideProgressIndicator() { 
     logger.info("Hide progress indicator here"); 
    } 

    @Override 
    public void onSuccess() { 
     logger.info("Api calls successfull"); 
     System.exit(0); 
    } 

    @Override 
    public void onFailure() { 
     logger.warning("Api call failure"); 
     System.exit(0); 
    } 

    @Override 
    public void onFailure(String message) { 
     logger.warning(message); 
     System.exit(0); 
    } 

    @Override 
    public void onListItems(List<Post> items, int pageNum, int pageSize, boolean next) { 
     logger.info("List received is: " + new Gson().toJson(items)); 
    } 

    @Override 
    public void onEmpty(String e) { 
     throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 
    } 

    public static void main(String[] args) { 
     ApiComponent apiComponent = DaggerApiComponent.builder() 
       .apiModule(new ApiModule("https://jsonplaceholder.typicode.com/")) 
       .build(); 

     NetworkTest networkTest = new NetworkTest(apiComponent); 
     networkTest.init(); 
     networkTest.showPosts(); 
    } 

} 

我的问题是,当我尝试使用

void inject(NetworkTest networkTest); //It works 
void inject(PostView postView); //Doesn't work 

我想那应该PostPresenter在谁正在实施PostView任何类得到注射。

但是当我这样做@Inject字段返回null。 有没有人对此有任何线索。

回答

1

NetworkTest有一个@Inject字段,Dagger可以在编译时检测到这个字段。 PostView不。 Dagger 2可以在NetworkTest和PostView上执行注入,但由于PostView没有注入方法,所以Dagger 2无法注入。

如果你想表达览的是任意的实现者可以注射,您应该添加一个@Inject -annotated initializeinjectPresenter方法(等);否则,只需从Dagger获取/注入具体类型,以便它们的所有依赖可以立即注入。


正如Dagger 2 user's guide(重点矿山)说,“匕首是完全静态的,编译时依赖注入Java和Android的框架。”与Guice或Spring不同,Dagger 2不执行运行时反射,因此(例如)生成的Component方法inject(PostView)只能在PostView或其超类型上注入定义为的字段和方法,而不是在子类型上定义的任何东西。

从一般意义上说,我不认为您期望(或约束)接口实现者需要以某种方式注入演示者是合理的;如果你想做一个明确的主持人 - 提供生命周期方法,你可以在PostView上做到这一点,而不涉及Dagger,这样你的类可以更具体地依赖它们的依赖关系,而不是将必要的deps与“不必要但包含的”你开了一个礼拜。

+0

是我的上述方法正确。 – sector11

+0

或者你可以建议如果它看起来不对,请更正。 – sector11

+0

@ sector11在我的回答中,我描述了两种方法 - 在PostView中添加@ @ Inject方法,或者只是注入具体类型 - 在技术上是可行的,但我喜欢后者,因为我在最后一段中说过的所有原因。你需要做出工程决定,哪一个更适合你的用例。 –