К сожалению, я не использую даже самые простые примеры кинжалов. Давайте посмотрим на мой код (я избавилась большинство UI и автоматически генерируемой кода, как это было не актуально):
Кинжал постоянно отказывается вводить зависимость
Моя активность
public class MainActivity extends ActionBarActivity { @Inject RoomDAO roomDAO; private ObjectGraph objectGraph; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); objectGraph = ObjectGraph.create(RoomModule.class); roomDAO = objectGraph.get(RoomDAO.class); roomDAO.hai(); } }
RoomDAO & RoomDAOImpl
public interface RoomDAO { String hai(); } public class RoomDAOImpl implements RoomDAO { private DBHelper dbHelper; @Inject public RoomDAOImpl(){ //I tried even this constructor in case dbHelper was the guy causing problems, //but it wasn't! } public RoomDAOImpl(DBHelper dbHelper){ this.dbHelper = dbHelper; } @Override public String hai() { return "oh hai"; } }
RoomModule
@Module( injects = {MainActivity.class}, library = true ) public class RoomModule { @Provides @Singleton public RoomDAO provideRoomDao(){ return new RoomDAOImpl(); } }
DBHelper
не имеет ничего интересного (только некоторые маленькие вещи баз данных, OnCreate, OnUpdate, больше ничего на самом деле).
Я думал, что линия roomDAO = objectGraph.get(RoomDAO.class);
заставит Кинжал (более или менее) позвонить RoomModule#provideRoomDao()
и сделать меня приятным, новым объектом RoomDAOImpl (или взять его с неба, если он уже создан). Тем не менее, мой график не имеет RoomDAO
в injectableTypes
, поэтому мое приложение не работает по строке roomDAO = objectGraph.get(RoomDAO.class);
при вызове ObjectGraph#getInjectableTypeBinding
(потому что moduleClass == null
). Что мне не хватает?
EDIT.
ОК, возможно, настало время показать, как выглядит DBHelper.
public class DBHelper extends SQLiteOpenHelper {
// (...) not relevant config stuff i.e. DATABASE_NAME, DATABASE_VERSION
@Inject
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
//(...) creating tables
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//(...) updating tables
}
}
@Module(
injects = {MainActivity.class}
)
public class RoomModule {
@Provides @Singleton
public RoomDAO provideRoomDao(DBHelper dbHelper){
return new RoomDAOImpl(dbHelper);
}
@Provides
public Context getAppContext(){
return MainActivity.getAppContext();
}
}
я решил использовать второй подход вы предложили, как это кажется более весна, как и я больше знаком с этим. MainActivity.getAppContext();
- статический метод, возвращающий значение статического поля Context. Это немного смущает, но я довольно неосведомлен, если дело доходит до контекста, поскольку я никогда не видел его реального использования (я всегда ставил this
, где мне нужен контекст).
Вот где возникает вопрос - RoomModule#getAppContext()
кажется вероятным источником ошибок? DBHelper
, вероятно, будет хорошо, потому что это синглтон и когда-то созданный он должен быть теоретически доступен повсюду. Добавляет ли какой-то определитель этому парню @Provides public Context getAppContext()
собирается сделать это решение более или менее свободным от ошибок? Или, может быть, есть лучший способ предоставить контекст для конструктора DBHelper
?
Здравствуйте, спасибо за ваше время и ответ, который сработал. Я решил использовать второй подход, который вы предложили. Во всяком случае, вы предсказывали, что я буду делать дальше, и здесь идет не-макетная версия конструктора RoomDAO. Я отредактировал свой вопрос, поскольку у DBHelper нет этого тривиального конструктора, поскольку он использует Context. Не могли бы вы еще раз взглянуть на мой вопрос и попытаться оценить, совершил ли я преступление или нет? ;) – spoko
Да, это правильный настрой. Лучший способ предоставить контекст - передать его конструктору вашего RoomModule и сохранить его как поле. Тогда вам не нужен статический вызов getAppContext. – nhaarman
Обратите внимание, что вы сделали правильную вещь, чтобы вернуть контекст приложения, а не только экземпляр Activity. Обход контекста активности опасен и известен как источник утечки памяти. – nhaarman