【问题标题】:Android: Dagger 2 constructor injection does not call the constructor and ends up in NPEAndroid:Dagger 2构造函数注入不调用构造函数,最终进入NPE
【发布时间】:2019-02-17 22:59:54
【问题描述】:

嗯,我浏览了所有 SO 帖子以及在线教程和博客。我似乎无法理解我的 dagger 2 构造函数注入中 nullpointer 异常背后的原因。

问题是构造函数没有被调用,而是调用,

public void getMobileDataUsage(OnDatastoreResponse onDatastoreResponse)

并导致一个空指针

我有一个使用构造函数注入的单例 APIClient 类。

@Singleton
public class APIClient {

private static final String TAG = "APIClient";

private APIInterface apiInterface;
private Retrofit retrofit;

@Inject
public APIClient(Context context) {
    // use 10MB cache
    long cacheSize = 10 * 1024 * 1024;
    Cache cache = new Cache(context.getCacheDir(), cacheSize);

    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).cache(cache).build();

    retrofit = new Retrofit.Builder()
            .baseUrl(BuildConfig.BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .client(client)
            .build();

    this.apiInterface = retrofit.create(APIInterface.class);
}

public void getMobileDataUsage(OnDatastoreResponse onDatastoreResponse) {
    String resourceId = "a807b7ab-6cad-4aa6-87d0-e283a7353a0f";
    Integer limit = null;

    Single<DatastoreResponse> datastoreResponse = apiInterface.getMobileDataUsage(resourceId, limit);
    datastoreResponse.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new DisposableSingleObserver<DatastoreResponse>() {
                @Override
                public void onSuccess(DatastoreResponse datastoreResponse) {
                    if (datastoreResponse.getSuccess()) {
                        Log.d(TAG, "onSuccess: " + datastoreResponse.getSuccess());

                        onDatastoreResponse.onSuccessDatastoreResponse(datastoreResponse);

                    } else {
                        Log.e(TAG, "onSuccess: " + datastoreResponse.getSuccess());
                        onDatastoreResponse.onErrorResponse(new Exception("Datastore response not successful"));
                    }
                }

                @Override
                public void onError(Throwable e) {
                    Log.e(TAG, "onError: " + e.getMessage(), e);
                    onDatastoreResponse.onErrorResponse(e);
                }
            });
}

}

我有一个提供者为上述构造函数注入提供上下文。

@Module
public class ApplicationContextModule {

private final Context context;

public ApplicationContextModule(Context context) {
    this.context = context;
}

@Provides
Context provideApplicationContext() {
    return context;
}

}

下面是我的ApplicationComponent,

@Singleton
@Component(modules = {ApplicationContextModule.class, DataModule.class})
public interface ApplicationComponent {

void inject(MobileDataUsageActivity mobileDataUsageActivity);

APIClient apiClient();

Context context();

}

构建组件的我的应用程序类,

public class MyApplication extends Application {

private ApplicationComponent applicationComponent;

@Override
public void onCreate() {
    super.onCreate();

    applicationComponent = DaggerApplicationComponent
            .builder()
            .applicationContextModule(new ApplicationContextModule(this))
            .dataModule(new DataModule())
            .build();

}

public ApplicationComponent getApplicationComponent() {
    return applicationComponent;
}
}

我在我的活动的 onCreate 期间注入实例,

((MyApplication) getApplication()).getApplicationComponent().inject(this);

最后是抛出空指针异常的存储库类。注意我有@Inject APIClient。但是在调试之后我注意到 APIClient 是 null 因为它没有调用构造函数。

public class MobileDataRepository {

private static final String TAG = "MobileDataRepository";

@Inject
APIClient apiClient;

private List<Quarter> quarterList = new ArrayList<>();
private List<Year> yearList = new ArrayList<>();

private MutableLiveData<List<Year>> mutableYearList = new MutableLiveData<>();

public LiveData<List<Year>> getYearlyMobileDataUsage() {
    apiClient.getMobileDataUsage(new OnDatastoreResponse() {
        @Override
        public void onSuccessDatastoreResponse(DatastoreResponse datastoreResponse) {

            for (QuarterResponse q : datastoreResponse.getResult().getRecords()) {
                Log.d(TAG, "Quarter: " + q.get_id() + " : " + q.getQuarter());

                String quarterInfo[] = q.getQuarter().split("-");
                String year = quarterInfo[0];
                String quarterName = quarterInfo[1];

                quarterList.add(new Quarter(q.get_id(), q.getVolume_of_mobile_data(), Integer.parseInt(year), quarterName));
            }
            mutableYearList.setValue(yearList);
        }

        @Override
        public void onErrorResponse(Throwable e) {

        }
    });

    return mutableYearList;

}

}

并且告诉APIClient实例没有创建的异常(注:我已经调试验证APIClient为null),

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.channa.mobiledatausageapp/com.channa.mobiledatausageapp.view.MobileDataUsageActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.channa.mobiledatausageapp.network.APIClient.getMobileDataUsage(com.channa.mobiledatausageapp.network.action.OnDatastoreResponse)' on a null object reference

对于庞大的代码,我们深表歉意。我只是想指出我已经完成了所需的一切,但由于某些奇怪的原因,构造函数 DI 不起作用。我什至尝试使用@Provider for APIClient 仍然错误相同。提前致谢!

哦,我用的是匕首版本:2.15

// Dagger 2
implementation "com.google.dagger:dagger:$rootProject.daggerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$rootProject.daggerVersion"

【问题讨论】:

    标签: java android dagger-2 dagger


    【解决方案1】:

    要进行此注入,您必须在 ApplicationComponent 中创建一个方法 void inject(MobileDataRepository mobileRepository),然后在 MobileDataRepository 中获取对该组件的引用并调用此 inject 某处的方法(例如,在构造函数中)

    或者,为了让它变得更好,因为您已经有一个注入方法可以将依赖项注入到您的 MobileDataUsageActivity 中,您可以在 MobileDataRepository 中创建一个带有 @Inject 注释的构造函数> 然后将其注入您的活动。它看起来像这样:

    class MobileDataRepository { 
        @Inject
        public MobileDataRepository(APIClient apiClient) 
        { //do your initialization } 
    }
    

    然后,在您的活动中:

    class MobileDataUsageActivity {
    
        @Inject MobileDataRepository mobileDataRepository
    
    // other code 
    }
    

    附:对不起格式,我是用手机写的:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-01
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 2011-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多