Ответ 1
Наконец, я нашел способ разрешить сбои, вызванные использованием Dagger 2 под Android 7.0 для моего приложения. Обратите внимание: это не устраняет проблему, когда пользовательское приложение не используется должным образом в Android 7.0. В моем случае у меня не было важной логики в моем настраиваемом приложении, кроме того, что был реализован Dagger 2, и поэтому я просто заменил реализацию DaggerApplication
на ApplicationlessInjection
ниже.
Известные проблемы
- Никакой инъекции зависимостей в пользовательских классах приложений (возможно, это не очень хорошая идея с безумными версиями OEM 7.0 OEM).
- Не все компоненты Dagger, модифицированные мной, я заменил только
DaggerAppCompatActivity
,DaggerIntentService
иDaggerFragment
. Если вы используете другие компоненты, такие какDaggerDialogFragment
илиDaggerBroadcastReceiver
, вам нужно создать свои собственные инструменты, но я думаю, что это не должно быть слишком сложно:)
Реализация
Остановить использование DaggerApplication
. Расширьте свое приложение снова из стандартного Application
или полностью избавитесь от пользовательского приложения. Для инъекции зависимостей с кинжалом 2 он больше не нужен. Просто расширяйте, например. FixedDaggerAppCompatActivity
, и вам хорошо пойти с Dagger 2 DI для занятий.
Вы можете заметить, что я все еще передаю контекст приложения в ApplicationlessInjection.getInstance()
. Сам по себе инъекции зависимостей совсем не нужен контекст, но я хочу иметь возможность легко вставлять контекст приложения в мои другие компоненты и модули. И там меня не волнует, является ли контекст приложения моим пользовательским приложением или каким-то сумасшедшим другим материалом с Android 7.0, если это контекст.
ApplicationlessInjection
public class ApplicationlessInjection
implements
HasActivityInjector,
HasFragmentInjector,
HasSupportFragmentInjector,
HasServiceInjector,
HasBroadcastReceiverInjector,
HasContentProviderInjector {
private static ApplicationlessInjection instance = null;
@Inject DispatchingAndroidInjector<Activity> activityInjector;
@Inject DispatchingAndroidInjector<BroadcastReceiver> broadcastReceiverInjector;
@Inject DispatchingAndroidInjector<android.app.Fragment> fragmentInjector;
@Inject DispatchingAndroidInjector<Fragment> supportFragmentInjector;
@Inject DispatchingAndroidInjector<Service> serviceInjector;
@Inject DispatchingAndroidInjector<ContentProvider> contentProviderInjector;
public ApplicationlessInjection(Context applicationContext) {
AppComponent appComponent = DaggerAppComponent.builder().context(applicationContext).build();
appComponent.inject(this);
}
@Override
public DispatchingAndroidInjector<Activity> activityInjector() {
return activityInjector;
}
@Override
public DispatchingAndroidInjector<android.app.Fragment> fragmentInjector() {
return fragmentInjector;
}
@Override
public DispatchingAndroidInjector<Fragment> supportFragmentInjector() {
return supportFragmentInjector;
}
@Override
public DispatchingAndroidInjector<BroadcastReceiver> broadcastReceiverInjector() {
return broadcastReceiverInjector;
}
@Override
public DispatchingAndroidInjector<Service> serviceInjector() {
return serviceInjector;
}
@Override
public AndroidInjector<ContentProvider> contentProviderInjector() {
return contentProviderInjector;
}
public static ApplicationlessInjection getInstance(Context applicationContext) {
if(instance == null) {
synchronized(ApplicationlessInjection.class) {
if (instance == null) {
instance = new ApplicationlessInjection(applicationContext);
}
}
}
return instance;
}
}
FixedDaggerAppCompatActivity
public abstract class FixedDaggerAppCompatActivity extends AppCompatActivity implements HasFragmentInjector, HasSupportFragmentInjector {
@Inject DispatchingAndroidInjector<Fragment> supportFragmentInjector;
@Inject DispatchingAndroidInjector<android.app.Fragment> frameworkFragmentInjector;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
inject();
super.onCreate(savedInstanceState);
}
@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return supportFragmentInjector;
}
@Override
public AndroidInjector<android.app.Fragment> fragmentInjector() {
return frameworkFragmentInjector;
}
private void inject() {
ApplicationlessInjection injection = ApplicationlessInjection.getInstance(getApplicationContext());
AndroidInjector<Activity> activityInjector = injection.activityInjector();
if (activityInjector == null) {
throw new NullPointerException("ApplicationlessInjection.activityInjector() returned null");
}
activityInjector.inject(this);
}
}
FixedDaggerFragment
public abstract class FixedDaggerFragment extends Fragment implements HasSupportFragmentInjector {
@Inject DispatchingAndroidInjector<Fragment> childFragmentInjector;
@Override
public void onAttach(Context context) {
inject();
super.onAttach(context);
}
@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return childFragmentInjector;
}
public void inject() {
HasSupportFragmentInjector hasSupportFragmentInjector = findHasFragmentInjector();
AndroidInjector<Fragment> fragmentInjector = hasSupportFragmentInjector.supportFragmentInjector();
if (fragmentInjector == null) {
throw new NullPointerException(String.format("%s.supportFragmentInjector() returned null", hasSupportFragmentInjector.getClass().getCanonicalName()));
}
fragmentInjector.inject(this);
}
private HasSupportFragmentInjector findHasFragmentInjector() {
Fragment parentFragment = this;
while ((parentFragment = parentFragment.getParentFragment()) != null) {
if (parentFragment instanceof HasSupportFragmentInjector) {
return (HasSupportFragmentInjector) parentFragment;
}
}
Activity activity = getActivity();
if (activity instanceof HasSupportFragmentInjector) {
return (HasSupportFragmentInjector) activity;
}
ApplicationlessInjection injection = ApplicationlessInjection.getInstance(activity.getApplicationContext());
if (injection != null) {
return injection;
}
throw new IllegalArgumentException(String.format("No injector was found for %s", getClass().getCanonicalName()));
}
}
FixedDaggerIntentService
public abstract class FixedDaggerIntentService extends IntentService {
public FixedDaggerIntentService(String name) {
super(name);
}
@Override
public void onCreate() {
inject();
super.onCreate();
}
private void inject() {
ApplicationlessInjection injection = ApplicationlessInjection.getInstance(getApplicationContext());
AndroidInjector<Service> serviceInjector = injection.serviceInjector();
if (serviceInjector == null) {
throw new NullPointerException("ApplicationlessInjection.serviceInjector() returned null");
}
serviceInjector.inject(this);
}
}
Мой AppComponent
@Singleton
@Component(modules = {
AppModule.class,
ActivityBindingModule.class,
AndroidSupportInjectionModule.class
})
public interface AppComponent extends AndroidInjector<ApplicationlessInjection> {
@Override
void inject(ApplicationlessInjection instance);
@Component.Builder
interface Builder {
@BindsInstance
AppComponent.Builder context(Context applicationContext);
AppComponent build();
}
}
Мой AppModule
@Module
public abstract class AppModule {
@Binds
@ApplicationContext
abstract Context bindContext(Context applicationContext);
}
И для полноты моей аннотации @ApplicationContext
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ApplicationContext {}
Надеюсь, я могу помочь кому-то еще с моим кодом. Для меня я смог разрешить все сбои, связанные с введением Dagger 2 и странных версий Android 7.0.
Если требуется больше разъяснений, просто дайте мне знать!