Инъекция поля Dagger 2 не работает в Android

avatar
Yamashiro Rion
8 апреля 2018 в 05:43
1006
1
2

Проблема в том, что я пытаюсь использовать внедрение поля с Dagger 2, но во время выполнения поле, которое должно быть введено, всегда null. Также я пытаюсь использовать шаблон MVVM. Вот мой код:

ProfileActivity.java:

@Override
protected void onStart() {
    super.onStart();
    Log.d(TAG, "ProfileActivity: onStart: ");

    final ProfileViewModel profileViewModel 
         = ViewModelProviders.of(this).get(ProfileViewModel.class);
    profileViewModel.init();
    profileViewModel.getUser().observe(this, new Observer<User>() {
        @Override
        public void onChanged(@Nullable User user) {
            if (user != null) {
                Log.d(TAG, "ProfileActivity: onStart: " + user.toString());
            } else {
                Log.d(TAG, "ProfileActivity: onStart: user == null");
            }
        }
    });
}

ProfileViewModel.java:

public class ProfileViewModel extends ViewModel {
    private LiveData<User> user;

    @Inject
    UserRepository userRepository;

    public ProfileViewModel() {
        Log.d(TAG, "ProfileViewModel: Constructor: ");
    }

    public void init() {
        Log.d(TAG, "ProfileViewModel: init: ");
        user = userRepository.getUser();
    }

    public LiveData<User> getUser() {
        Log.d(TAG, "ProfileViewModel: getUser: ");
        return user;
    }
}

UserRepository.java:

@Singleton
public class UserRepository {
    private LiveData<User> user;

    @Inject
    public UserRepository() {
        Log.d(TAG, "UserRepository: Constructor: ");
    }

    public LiveData<User> getUser() {
        Log.d(TAG, "UserRepository: getUser: ");
        if (user != null) {
            return user;
        } else {
            // There should be userDao.load() call,
            // but it had been omitted for brevity.
            MutableLiveData<User> user = new MutableLiveData<>();
            user.setValue(DB.getUser());
            return user;
        }
    }
}

MyApplication.java:

public class MyApplication extends MultiDexApplication implements HasActivityInjector {
    @Inject
    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

    @Override
    public void onCreate() {
        super.onCreate();
        DaggerMyApplicationComponent.create().inject(this);
    }

    @Override
    public DispatchingAndroidInjector<Activity> activityInjector() {
        return dispatchingAndroidInjector;
    }
}

MyApplicationModule.java:

@Module
public abstract class MyApplicationModule {
    @ContributesAndroidInjector
    abstract ProfileActivity contributeActivityInjector();
}

MyApplicationComponent.java:

@Component(modules = { AndroidInjectionModule.class, MyApplicationModule.class})
@Singleton
public interface MyApplicationComponent extends AndroidInjector<MyApplication> {
    void inject(ProfileActivity profileActivity);
}

Во время выполнения я вижу следующие журналы:

ProfileActivity: onStart:
ProfileViewModel: Constructor:
ProfileViewModel: init:

И приложение падает на user = userRepository.getUser(); внутри метода ProfileViewModel init().

Это означает, что UserRepository не был введен. Также на это указывает отсутствие журнала UserRepository: Constructor:.

Где моя ошибка? Спасибо.

Источник

Ответы (1)

avatar
Tomas Jablonskis
8 апреля 2018 в 05:58
5

В основном вам нужно использовать ViewModel Factory для передачи введенного UserRepository в ваш конструктор ViewModels, инициализировать его, и тогда вы сможете его использовать. Вы не можете использовать вставки полей или параметров в ViewModels.

Я бы посоветовал вам следовать этой статье: Добавить новую ViewModel в ваш MVVM

В нем достаточно информации, чтобы начать использовать Dagger 2 с компонентами архитектуры.


Надеюсь, это поможет.

Yamashiro Rion
8 апреля 2018 в 09:00
0

Большое спасибо, вы спасли мой день! Проблема решена.