Dagger NullPointerException 3rd class depending on 2nd class

0

In a project that has Activity, Presenter, and Model, Activity has Presenter and Presenter has a Model. When I do @Inject in Presenter to instantiate the Model it is never instantiated.

  

FATAL EXCEPTION: main                                                                                    Process: fipedaggerrxjava, PID: 22258                                                                                    java.lang.NullPointerException: Attempt to invoke interface method   void   fipedaggerrxjava.mvp.SelectMarcaContractMVP $ Model.getMarcas (java.lang.String) '   on a null object reference                                                                                        at   fipedaggerrxjava.module.marca.MarcaPresenter.initData (MarcaPresenter.java:35)                                                                                        at   fipedaggerrxjava.module.marca.MarcaActivity $ 1.onCheckedChanged (MarcaActivity.java:63)

I have already checked in Debug and really the Model that is not being instantiated by Dagger but I can not understand why.

App

public class App extends Application implements HasActivityInjector{

    @Inject
    public DispatchingAndroidInjector<Activity> activityDispatchingAndroidInjector;


    @Override
    public void onCreate() {
        super.onCreate();
        DaggerAppComponent.builder().build().inject(App.this);
    }

    @Override
    public AndroidInjector<Activity> activityInjector() {
        return activityDispatchingAndroidInjector;
    }
}

ActivityBuilder

@Module
public abstract class ActivityBuilder {

    @Binds
    @IntoMap
    @ActivityKey(MarcaActivity.class)
    abstract AndroidInjector.Factory<? extends Activity> bindMarcaActivity (MarcaComponent.Builder builder);

}

AppComponent

@Component(modules = {ActivityBuilder.class, AndroidInjectionModule.class, AppModule.class})
@Singleton
public interface AppComponent {

    void inject(App app);

}

AppModule

@Module(subcomponents = MarcaComponent.class)
public class AppModule {

    @Provides
    @Singleton
    @Named("URL_MARCA")
    String provideStringURLBase(){
        return "https://fipe.parallelum.com.br/api/v1/";
    }

    @Provides
    @Singleton
    Context provideContext(App app){
        return app;
    }

    @Provides
    @Singleton
    Gson provideGsonRepositorie(){
        return new GsonBuilder()
                .create();
    }


    @Singleton
    @Provides
    OkHttpClient provideOkHttpCliente1(){
        return new OkHttpClient.Builder()
                .connectTimeout(20, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .build();
    }


    @Singleton
    @Provides
    RxJavaCallAdapterFactory provideRxJavaCallAdapterFactory(){
        return RxJavaCallAdapterFactory.create();
    }


    @Provides
    @Singleton
    Retrofit provideRetrofit(OkHttpClient okHttpClient, Gson gson, RxJavaCallAdapterFactory rxAdapter, @Named("URL_MARCA") String stringBaseURL){
        return new Retrofit.Builder()
                .baseUrl(stringBaseURL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(rxAdapter)
                .client(okHttpClient)
                .build();
    }
}

MarcaComponent

@Subcomponent(modules = MarcaModule.class)
@PerMarca
public interface MarcaComponent extends AndroidInjector<MarcaActivity>{

    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder<MarcaActivity> {}

}

MarcaModule

@Module
public class MarcaModule{


    @Provides
    @PerMarca
    APIFIPE provideAPIFIPE(Retrofit retrofit){
        return retrofit.create(APIFIPE.class);
    }


    @Provides
    @PerMarca
    View provideViewMarca(MarcaActivity activity){
        return activity;
    }


    @Provides
    @PerMarca
    Presenter providePresenterMarca(){
        return new MarcaPresenter();
    }


    @Provides
    @PerMarca
    Model provideModelMarca(){
        return new MarcaModel();
    }


}

AdapterBrand

public class AdapterMarca extends BaseAdapter {

private List<Marca> mListMarca;

@Inject
public Context mContext;

public AdapterMarca(List<Marca> listMarca){
    this.mListMarca = listMarca;
}


@Override
public int getCount() {
    return mListMarca.size();
}

@Override
public Object getItem(int position) {
    return mListMarca.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.layout_list_item, parent, false);

    TextView tvNome = view.findViewById(R.id.tv_marca);
    tvNome.setText(mListMarca.get(position).getName().toString());

    return view;
}


public void addListMarca(List<Marca> marcaList){
    mListMarca.clear();
    mListMarca.addAll(marcaList);
    notifyDataSetChanged();
}

}

MarcaActivity

public class MarcaActivity extends BaseActivity implements HasActivityInjector, View {

    private RadioGroup radioGroupMarca;
    private String tipoSelect = "";

    private List<Marca> mListMarca;
    private AdapterMarca mAdapterMarca;

    private ListView listViewMarca;


    @Inject
    public Presenter mMarcaPresenter;

    @Inject
    protected DispatchingAndroidInjector<Activity> activityDispatchingAndroidInjector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        AndroidInjection.inject(MarcaActivity.this);
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        listViewMarca = findViewById(R.id.lv_marca);


        radioGroupMarca = findViewById(R.id.rg_tipo);

        radioGroupMarca.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                int id = group.getCheckedRadioButtonId();

                switch (id){
                    case R.id.rb_carros : tipoSelect = "carros";
                        mMarcaPresenter.initData(tipoSelect);
                        break;

                    case R.id.rb_motos : tipoSelect = "motos";
                        mMarcaPresenter.initData(tipoSelect);
                        break;

                    case R.id.rb_caminhoes : tipoSelect = "caminhoes";
                        mMarcaPresenter.initData(tipoSelect);
                        break;
                }
            }
        });



    }



    @Override
    public AndroidInjector<Activity> activityInjector() {
        return activityDispatchingAndroidInjector;
    }



    @Override
    public void onMarcaLoader(List<Marca> listMarcas) {
        if(mListMarca==null && listMarcas!=null){
            initListView();
        }

        if(mAdapterMarca!=null){
            mListMarca.clear();
            mListMarca = listMarcas;

            mAdapterMarca.addListMarca(mListMarca);
        }

    }


    private void initListView(){
        mAdapterMarca = new AdapterMarca(mListMarca);
        listViewMarca.setAdapter(mAdapterMarca);
    }

}

MarcaPresenter

@PerMarca
public class MarcaPresenter implements Presenter {

    @Inject
    View mMarcaView;


    @Inject
    Model mMarcaModel;

    @Inject
    public MarcaPresenter(){

    }


    @Override
    public void initData(String tipoMarca) {
        mMarcaModel.getMarcas(tipoMarca);
    }

    @Override
    public void getMarcas(List<Marca> listMarcas) {
        mMarcaView.onMarcaLoader(listMarcas);
    }

    @Override
    public void onShowDialog(String title, String msg) {
        mMarcaView.onShowDialog(title, msg);
    }

    @Override
    public void onHideShowDialog() {
        mMarcaView.onHideShowDialog();
    }

    @Override
    public void onShowToast(String s) {
        mMarcaView.onShowToast(s);
    }
}

MarcaModel

@PerMarca
public class MarcaModel implements Model {

    @Inject
    APIFIPE mApiFIPE;

    @Inject
    Presenter mMarcaPresenter;


    @Inject
    public MarcaModel(){

    }

    @Override
    public void getMarcas(String tipoVeiculo) {
        final List<Marca> marcaList = new ArrayList<>();
        Observable<List<Marca>> observable = mApiFIPE.getRepositories(tipoVeiculo);
        observable.subscribe(new Observer<List<Marca>>() {
            @Override
            public void onCompleted() {
                mMarcaPresenter.getMarcas(marcaList);
            }

            @Override
            public void onError(Throwable e) {
                mMarcaPresenter.onShowDialog("Erro", "Falha ao carregar lista de marcas");
            }

            @Override
            public void onNext(List<Marca> marcas) {
                marcaList.addAll(marcas);
            }
        });



    }
}
    
asked by anonymous 19.03.2018 / 22:39

1 answer

0

Let Dagger automatically inject your Presenter and Model from the dependency graph, that is, you do not need to instantiate them within the module.

There's also a better way to inject activities on Android with the annotation: @ContributesAndroidInjector , will greatly decrease boilerplate tags. Here's a great article telling you how to do it: link

EDIT

I've made some changes to your classes. You should not instantiate your objects, but instead do the inversion control, that is, Dagger will instantiate them for you.

MarcaModule

@Module
public class MarcaModule{
    ....

    @Provides
    @PerMarca
    Presenter providePresenterMarca(MarcaPresenter presenter){
        return presenter;
    }

    @Provides
    @PerMarca
    Model provideModelMarca(MarcaModel marca){
        return marca;
    }
}

MarcaActivity

public class MarcaActivity extends BaseActivity implements HasActivityInjector, View {
    ....

    @Inject
    AdapterMarca mAdapterMarca;

    ....

    private void initListView(){
        mAdapterMarca.addListMarca(mListMarca);
        listViewMarca.setAdapter(mAdapterMarca);
    }

}

AdapterBrand

public class AdapterMarca extends BaseAdapter {

    private List<Marca> mListMarca;

    @Inject
    Context mContext;

    public AdapterMarca(){
        this.mListMarca = new ArrayList();
    }
    ...
}
    
20.03.2018 / 01:21