ViewModel не имеет нулевой ошибки конструктора аргумента, вызванной ViewModelFactory, остается нулевым (не уверен на 100%) - PullRequest
0 голосов
/ 05 марта 2019

До сих пор я следовал руководству для разработчиков Android по компонентам архитектуры и, конечно, проблема была в том, что их примеры не могли работать с заводской установкой по умолчанию ' без исключения нулевого аргумента '.Я придерживался некоторой логики репозитория примеров Google, а также довольно большого количества предложений StackOverflow, а также блогов и учебных пособий.Но я все еще получаю ту же ошибку.

Теперь, Я думаю, что я обнаружил проблему , и похоже, что мой ViewModelFactory по-прежнему равен нулю, так что ViewModelProvider заменяет его на значение по умолчаниюФабрика, которая, конечно, ожидает конструктор с нулевым аргументом.Но я до сих пор не понимаю, что именно с кодом не так.

Так что у меня в основном есть ViewModelFactory

public class ViewModelFactory implements ViewModelProvider.Factory {

    private final Map<Class<? extends CustomViewModel>, Provider<CustomViewModel>> viewModels;

    @Inject
    public ViewModelFactory(Map<Class<? extends CustomViewModel>, Provider<CustomViewModel>> viewModels) {
        this.viewModels = viewModels;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T extends ViewModel> T create(Class<T> modelClass) {

        Provider<? extends CustomViewModel> viewModelProvider = viewModels.get(modelClass);

        if (viewModelProvider == null) {

            for (Map.Entry<Class<? extends CustomViewModel>, Provider<CustomViewModel>> entry : viewModels.entrySet()) {

                if (modelClass.isAssignableFrom(entry.getKey())) {

                    viewModelProvider = entry.getValue();
                    break;
                }
            }
        }

        if (viewModelProvider == null) {

            throw new IllegalArgumentException("unknown model class " + modelClass);
        }

        try {

            return (T) viewModelProvider.get();
        } catch (Exception e) {

            throw new RuntimeException(e);
        }
    }
}

и AppComponent

@Singleton
@Component(modules = {AndroidSupportInjectionModule.class, ViewModelModule.class})
public interface AppComponent {

    @Component.Builder
    interface Builder {

        @BindsInstance
        Builder application(App application);
        AppComponent build();
    }
    void inject(App application);
}

А затем ViewModelModule

@Module
public abstract class ViewModelModule {

    @Binds
    abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory viewModelFactory);

    @Binds
    @IntoMap
    @ViewModelKey(HourlyViewModel.class)
    abstract ViewModel bindHourlyViewModel(HourlyViewModel hourlyViewModel);
}

И ViewModelKey

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@MapKey
@interface ViewModelKey {

    Class<? extends CustomViewModel> value();
}

И ViewModel

public class HourlyViewModel extends CustomViewModel {

    private LiveData<HourlyData> hourlyData;
    private MainRepository mainRepo;

    @Inject
    public HourlyViewModel(HourlyRepository mainRepo) {

        this.mainRepo = mainRepo;
    }

    @Override
    public void init(int id, long start, long stop) {
        super.init(id, start, stop);

        // some logic
    }
}

И бонус CustomViewModel

public class CustomViewModel extends ViewModel {

    public OpenDataApi api;

    public int id;
    public long start;
    public long stop;

    /**
     *
     * @param id
     * @param start
     * @param stop
     */
    public void init(int id, long start, long stop) {

        api = OpenDataApi.getRetrofitInstance().create(OpenDataApi.class);
        this.id = id;
        this.start = start;
        this.stop = stop;
    }
}

Мое приложение

public class App extends Application {

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

        DaggerAppComponent
                .builder()
                .application(this)
                .build()
                .inject(this);

        AndroidThreeTen.init(this);
    }
}

И как я пытаюсь вызвать ViewModel во фрагменте

public class FragmentHourly extends Fragment {

    @Inject
    ViewModelFactory viewModelFactory;

    private HourlyViewModel viewModel;

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        viewModel = ViewModelProviders.of(this, viewModelFactory).get(HourlyViewModel.class);
    }
}

Что именно мне здесь не хватает?Моя реализация неверна или чего-то не хватает?

Приветствия и спасибо за помощь

1 Ответ

0 голосов
/ 21 августа 2019

Я также сталкивался с подобным блокировщиком, сегодня и ошибкой был следующий код, пропущенный во фрагменте:

`

@Override
public void onAttach(Context context) {
      AndroidSupportInjection.inject(this);
      super.onAttach(context);
}

`

...