当前位置: 首页 > 知识库问答 >
问题:

尝试使用依赖注入进行改进

何和惬
2023-03-14
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
@Singleton
@Component(modules = {NetModule.class,ApplicationModule.class})
public interface NetComponent {
    void inject(AppCompatActivity activity);
    void inject(Fragment fragment);
}
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;
    }
}

我尝试在我的活动中注入修改,但我得到了空异常

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个答案

乐正辰阳
2023-03-14

您应该在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
}
 类似资料:
  • 例如,Foos的资源可能如下所示: 对于酒吧:

  • 从零开始,没有任何以前的Jersey 1.x知识,我很难理解如何在我的Jersey 2.0项目中设置依赖注入。 我也知道HK2在Jersey 2.0中可用,但我似乎找不到有助于Jersey 2.0集成的文档。 我可以让容器启动并提供我的资源,但是当我将@inject添加到MyService时,框架就会抛出一个异常: 我的starter项目可在github:https://github.com/do

  • 问题在于Azure WebJobs SDK只支持公共静态方法作为作业入口点,这意味着无法实现构造函数/属性注入。 我在官方WebJobs SDK文档/资源中找不到有关此主题的任何内容。我遇到的唯一解决方案是基于本文描述的服务定位器(anti)模式。 对于基于Azure WebJobs SDK的项目,有没有一种好方法可以使用“适当的”依赖项注入?

  • 我正在尝试使用Jersey测试框架为我的REST API编写功能测试。然而,当我在功能测试中使用依赖注入时,我似乎遇到了一个障碍。我的主应用程序看起来是这样的: 是否有一种方法可以将HK2服务定位器与Jersey测试框架一起使用,或者我是否需要将我的应用程序视为外部容器并使用外部容器提供程序,如这里所述:外部容器? 此外,由于这些是功能测试,因此在这里不允许对注入的服务进行嘲弄。

  • 问题内容: 我的团队正在研究依赖项注入框架,并试图在使用Google-Guice和PicoContainer之间做出选择。 我们正在寻找框架中的几件事情: 较小的代码占用空间-我的意思是较小的代码占用空间是我们不想在我们的代码库中到处都有依赖项注入代码垃圾。如果我们需要在将来进行重构,我们希望它尽可能简单。 性能-创建和注入对象时,每个框架有多少开销? 易于使用-学习曲线是否很大?我们是否必须编写

  • 好的,到目前为止还好。但是等等,突然A需要额外的输入,比如一个对它的构造至关重要的名为“amount”的整数。现在,我的A构造函数需要如下所示: 突然这个新参数干扰了注射。此外,即使这确实有效,我也无法在从提供者检索新实例时输入“金额”,除非我弄错了。这里有几件事我可以做,我的问题是哪一件是最好的? 我可以通过添加一个方法来重构A,该方法应该在构造函数之后调用。然而,这是很难看的,因为它迫使我推迟