Dagger 2未插入接口类型 [英] Dagger 2 not injecting in interface type

查看:87
本文介绍了Dagger 2未插入接口类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图以由类实现的接口类型注入字段。

I an trying to inject a field in an interface type which is implemented by a class.

这是我到目前为止所做的。

Here is what i have done so far.

以下是视图界面:

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:

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

}

我的问题是当我尝试使用

My Problem is when i try to use

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

我想要 PostPresenter 应该在实现 PostView 的任何类中注入。

I want that PostPresenter should get Injected in any class who is implementing PostView.

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

But when i do this @Inject field return null. Does anyone have any clue about this.

推荐答案

NetworkTest的 @Inject 字段。 PostView没有。 Dagger 2可以在NetworkTest和PostView上执行注入,但是由于PostView没有 @Inject 注释的方法,因此Dagger 2没有注入任何东西。

NetworkTest has an @Inject field that Dagger can detect at compile time. PostView does not. Dagger 2 can perform injection on both NetworkTest and PostView, but because PostView has no @Inject-annotated methods, there's nothing for Dagger 2 to inject.

如果要表达可以注入PostView的任意实现者,则应添加 @Inject 注释的初始化 injectPresenter 方法(等);否则,只需从Dagger获取/注入具体类型,以便可以立即注入其所有依赖项。

If you want to express that arbitrary implementors of PostView can be injected, you should add an @Inject-annotated initialize or injectPresenter method (et al); otherwise, just get/inject concrete types from Dagger so all of their dependencies can be injected at once.

Dagger 2用户指南(重点是我的), Dagger是完全静态,可编译的- Java和Android的时间依赖项注入框架。与Guice或Spring不同,Dagger 2不执行任何运行时反射,因此(例如)生成的Component方法 inject(PostView)只能注入在上定义的字段和方法PostView或其超类型,而不是在子类型上定义的任何内容。

As stated in the Dagger 2 user's guide (emphasis mine), "Dagger is a fully static, compile-time dependency injection framework for both Java and Android." Unlike with Guice or Spring, Dagger 2 performs no runtime reflection, so (for instance) a generated Component method inject(PostView) can only inject fields and methods defined on PostView or its supertypes, and not anything defined on a subtype.

一般而言,我认为您期望的结果不合理(或约束)您的 PostView 接口实现者,要求以某种方式注入Presenter;如果您想使用显式的Presenter提供生命周期方法,则可以在不涉及Dagger的情况下在PostView上进行操作,这样,您的类可以更加具体地依赖于它们的依赖关系,而不是将必要的deps与不必要但包含的混合在一起随便你开。

In a general sense, I don't think it's reasonable for you to expect (or constrain) your PostView interface implementors to require the injection of a Presenter a certain way; if you want to make an explicit presenter-providing lifecycle method, you can do that on PostView without involving Dagger, and that way your classes can be more specific with their dependencies rather than mixing the necessary deps with the "unnecessary-but-included" deps you prescribe.

这篇关于Dagger 2未插入接口类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆