Dagger NullPointerException第3类取决于第2类

时间:2018-03-19 22:55:59

标签: java android dagger-2

在作为活动模型,演示者和模型的项目中,活动主题和演示者和演示者模型。当我在Presenter中执行@Inject来实例化模型时,它永远不会被实例化。

您是否需要依赖"级联"?

  

致命异常:主程序:fipedaggerrxjava,PID:22258   java.lang.NullPointerException:尝试调用接口方法   '空隙   fipedaggerrxjava.mvp.SelectMarcaContractMVP $ Model.getMarcas(java.lang.String中)'   在null对象引用   fipedaggerrxjava.module.marca.MarcaPresenter.initData(MarcaPresenter.java:35)   在   fipedaggerrxjava.module.marca.MarcaActivity $ 1.onCheckedChanged(MarcaActivity.java:63)

我已经检查过Debug,并且确实没有被Dagger实例化的模型,但我无法理解为什么。

应用

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


}

AdapterMarca

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



    }
}

2 个答案:

答案 0 :(得分:0)

以下行:

       * {
    margin: 0px;
    padding: 0px;
}

.header-container{
    position:fixed;
    top:0;
    left:0;
    width:100%;
    height:80px;
    background: #ccc;
    box-sizing: border-box;
    z-index: 10;
}
.left{
    padding-left: 50px;
    float:left;
}
.right{
    padding-left: 300px;
    float: left;
}
.main-container{

    position:absolute;
    margin-top: 80px;
    left:0px;
    width:100%;
    height: calc(100% - 80px);
    box-sizing: border-box;
    background-color: pink;
    z-index:1;
}
.left-column{
    position:relative;
    padding:0;
    margin:0;
    float:left;
    width:20%;
    height:100%;
    background-color: #4db6ac;
}
.main-column{
    position:relative;
    padding:0;
    margin:0;
    float:left;
    width:80%;
    height:100%;
    background-color: #00e5ff;
}

@media screen and (max-width:720px){
    .header-container{
        height: auto;
    }
    .left-column{
        display:none;
    }
    .main-column{
        width:100%;
    }
}

- 您尝试使用mMarcePResenter并注入它,但仍需要使用App的组件分配给mMarcaPresenter。

在下面的构造函数中初始化注入的值:

 public void onCompleted() {
     mMarcaPresenter.getMarcas(marcaList);
 } 

答案 1 :(得分:0)

您已为模型和演示者类声明了提供程序方法(在MarcaModule中)。 Dagger使用那些提供者方法,最终没有提供字段注入值。

因此,您需要在模块中提供依赖项,即通过Model和Presenter构造函数。

<强> MarcaModel

...
Presenter mMarcaPresenter;


@Inject
public MarcaModel(Presenter presenter){
    mMarcaPresenter = presenter
}
...

<强> MarcaModule

@Module
public class MarcaModule{
    ...

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

}

仔细阅读Dagger用户指南可能会对您有所帮助;

https://google.github.io/dagger/users-guide