尝试通过依赖注入获得Retrofit

时间:2017-03-24 10:55:44

标签: android retrofit2 dagger-2

我想在我的android应用程序中获取工作线索列表。我使用Dagger 2和Retrofit和OkHttp,但我收到此错误

    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.../com...AccueilActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object retrofit2.Retrofit.create(java.lang.Class)' on a null object reference
                                                                          at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3319)
                                                                          at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3415)
                                                                          at android.app.ActivityThread.access$1100(ActivityThread.java:229)
                                                                          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1821)
                                                                          at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                          at android.os.Looper.loop(Looper.java:148)
                                                                          at android.app.ActivityThread.main(ActivityThread.java:7325)
                                                                          at java.lang.reflect.Method.invoke(Native Method)
                                                                          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                                          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
                                                                       Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object retrofit2.Retrofit.create(java.lang.Class)' on a null object reference

我创建两个组件ApplicationComponent,NetComponent

@Singleton
@Component(modules = {NetModule.class,ApplicationModule.class})
public interface NetComponent {
void inject(AppCompatActivity activity);
void inject(Fragment fragment);
}

和Tow模块ApplicationModule,NetModule

import android.app.Application;
import dagger.Module;
import dagger.Provides;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import javax.inject.Singleton;
@Module
public class NetModule {
String baseUrl;
public NetModule(String baseUrl) {
    this.baseUrl = baseUrl;
}
@Provides
@Singleton
Cache provideOkHttpCache(Application application) {
    int cacheSize = 10 * 1024 * 1024; // 10 MiB
    Cache cache = new Cache(application.getCacheDir(), cacheSize);
    return cache;
}
@Provides
@Singleton
Gson provideGson() {
    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
    return gsonBuilder.create();
}

@Provides
@Singleton
OkHttpClient provideOkHttpClient(Cache cache) {
    OkHttpClient client = new OkHttpClient.Builder().cache(cache).build();
    return client;
}
@Provides
@Singleton
public Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
    Retrofit retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create(gson))
            .baseUrl(baseUrl)
            .client(okHttpClient)
            .build();
    return retrofit;
   }
}

我尝试在我的Activity中注入Retrofit,但我得到null异常

    public class AccueilActivity extends AppCompatActivity {
ArrayList<MenuItem> menu = new ArrayList<>();
@Inject
Retrofit retrofit;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_accueil);
((AndroidApplication) getApplicationContext()).getNetComponent().inject(this);
Call<List<JobLeads>> jobLeadList = retrofit.create(GetJobLeads.class).getJobLeads();
    jobLeadList.enqueue(new Callback<List<JobLeads>>() {
        @Override
        public void success(Result<List<JobLeads>> result) {

        }

        @Override
        public void failure(TwitterException exception) {

        }
    });
}

这是AndroidApplication类

public class AndroidApplication extends Application {

private ApplicationComponent applicationComponent;
private NetComponent netComponent;

@Override
public void onCreate() {
    super.onCreate();
    this.initializeInjector();
    SugarContext.init(this);
}


private void initializeInjector() {

    this.applicationComponent = DaggerApplicationComponent.builder()
            .applicationModule(new ApplicationModule(this))
            .build();
    this.netComponent = DaggerNetComponent.builder()
            .applicationModule(new ApplicationModule(this))
            .netModule(new NetModule(JOB_LEADS_API2))
            .build();

}

public ApplicationComponent getApplicationComponent() {
    return this.applicationComponent;
}

public NetComponent getNetComponent() {
    return this.netComponent;
}

@Override
public void onTerminate() {
    super.onTerminate();
    SugarContext.terminate();
}
}

1 个答案:

答案 0 :(得分:1)

你应该注入AccueilActivity而不是AppCompatActivity

@Singleton
@Component(modules = {NetModule.class,ApplicationModule.class})
public interface NetComponent {
void inject(AccueilActivity activity);
void inject(Fragment fragment);
}

编辑:这是我的工作示例:

创建一个InjectHelper,以便在其他类中重用

public class InjectHelper {
private static RootComponent sRootComponent;

static {
    initModules();
}

private static void initModules() {
    sRootComponent = getRootComponentBuilder().build();
}

public static DaggerRootComponent.Builder getRootComponentBuilder() {
    return DaggerRootComponent.builder();
}

public static RootComponent getRootComponent() {
    if (sRootComponent == null) {
        initModules();
    }
    return sRootComponent;
}
}

组件

@Singleton
@Component(modules = { NetModule.class })
public interface RootComponent {
    void inject(AccueilActivity activity);
    void inject(Fragment fragment);
}

具有改造实例的网络模块

@Module
public class NetModule {
    private static final int CONNECT_TIMEOUT = 45;
    private static final int WRITE_TIMEOUT = 45;
    private static final int READ_TIMEOUT = 45;
    private static final long CACHE_SIZE = 10 * 1024 * 1024; // 10 MB

    private Cache provideHttpCache() {
        return new Cache(App.getInstance().getCacheDir(), CACHE_SIZE);
    }

    /**
     * @return OkHttpClient.Builder an instance of the configured http client
     */
    private OkHttpClient provideOkHttpClient() {
        OkHttpClient.Builder client = new OkHttpClient.Builder();
        client.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS);
        client.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS);
        client.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS);
        client.cache(provideHttpCache());
        client.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (isConnected(App.getContext())) {
                    request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build();
                } else {
                    request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build(); // 1 week
                }
                return chain.proceed(request);
            }
        });
        return client.build();
    }

    private Gson provideGsonParser(){
        return new GsonBuilder()
                .setDateFormat("dd-MM-yyyy 'at' HH:mm")
                .create();
    }

    /**
     * Provides a singleton instance of Retrofit. This is injected with dagger DI into the baseDAO
     * @return Retrofit instance to create the api calls
     */
    @Provides
    @Singleton
    public Retrofit provideRetrofit() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(App.getContext().getString(R.string.base_url))
                .client(provideOkHttpClient())
                .addConverterFactory(GsonConverterFactory.create(provideGsonParser()))
                .build();
        return retrofit;
    }

    private boolean isConnected(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm == null) {
            return false;
        }
        NetworkInfo info = cm.getActiveNetworkInfo();
        return info != null && info.isConnected();
    }
}

在您的活动中注入:

public class MainActivity extends AppCompatActivity {
@Inject
Retrofit retrofit;
private ApiService service;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
InjectHelper.getRootComponent().inject(this); // call the InjectHelper
service = retrofit.create(ApiService.class); // use retrofit
}