Использование Dagger 2 в классе SyncAdapter

Я использую Sync Adapter вместе с Dagger 2 для внедрения зависимостей. Я застрял, так как не могу понять, где мне использовать XYZ.inject, поскольку класс SyncAdapter не предоставляет OnCreate или Activity, которых можно придерживаться. Может ли кто-нибудь предложить, как бороться с инъекцией зависимостей в случае классов Sync Adapter, которые не принадлежат к активности / фрагменту? PS: Я рассмотрел несколько похожих вопросов, но не смог найти решения своей проблемы.

SyncAdapter.java

  public class SyncAdapter extends AbstractThreadedSyncAdapter {


ContentResolver mContentResolver;
//Injects here
@Inject
SyncCenterPresenter mSyncCenterPresenter;


private final AccountManager mAccountManager;

Context context;

public SyncAdapter(Context context, boolean autoInitialize) {
    super(context, autoInitialize);
    mContentResolver = context.getContentResolver();
    mAccountManager = AccountManager.get(context);
    this.context=context;
}
Account mainAccount;
public static final int SYNC_INTERVAL = 60 * 1;
public static final int SYNC_FLEXTIME = SYNC_INTERVAL/3;
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {

    Log.v("Sync class me","sync adapter on perform sync");
    if (mSyncCenterPresenter == null){
        Log.v("messsage","null");
    } else {
        Log.v("messsage","not null");
        mSyncCenterPresenter.loadDatabaseCenterPayload();
        mSyncCenterPresenter.syncPayload();
    }
}

/**
 * Helper method to schedule the sync adapter periodic execution
 */
public static void configurePeriodicSync(Context context, int syncInterval, int flexTime) {
    Account account = myAccount;
    String authority = "com.mifos.provider";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        // we can enable inexact timers in our periodic sync
        SyncRequest request = new SyncRequest.Builder().
                syncPeriodic(syncInterval, flexTime).
                setSyncAdapter(account, authority).
                setExtras(new Bundle()).build();
        ContentResolver.requestSync(request);
    } else {
        ContentResolver.addPeriodicSync(account,
                authority, new Bundle(), syncInterval);
    }
}
static Account myAccount;
public static void onAccountCreated(Account newAccount, Context context) {
    /*
     * Since we've created an account
     */
    myAccount = newAccount;
    SyncAdapter.configurePeriodicSync(context, SYNC_INTERVAL, SYNC_FLEXTIME);

    /*
     * Without calling setSyncAutomatically, our periodic sync will not be enabled.
     */
    ContentResolver.setSyncAutomatically(newAccount, "com.mifos.provider", true);

    /*
     * Finally, let's do a sync to get things started
     */
    syncImmediately(context);
}
public static Account getSyncAccount(Context context) {
    // Create the account type and default account
    Account newAccount = new Account(
            context.getString(R.string.app_name), "com.mifos");
    return newAccount;
}
/**
 * Helper method to have the sync adapter sync immediately
 * @param context The context used to access the account service
 */
public static void syncImmediately(Context context) {
    Bundle bundle = new Bundle();
    bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
    bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
    ContentResolver.requestSync(getSyncAccount(context),
            "com.mifos.provider", bundle);
}
  }

SyncCenterPresenter.java

  public class SyncCenterPresenter {
private final DataManagerCenter mDataManagerCenter;
private CompositeSubscription mSubscriptions;
List<CenterPayload> centerPayloads;
int mCenterSyncIndex = 0;

@Inject
public SyncCenterPresenter(DataManagerCenter dataManagerCenter) {
    Log.v("messsage","const me");
    mDataManagerCenter = dataManagerCenter;
    mSubscriptions = new CompositeSubscription();
    centerPayloads = new ArrayList<>();
}

public void loadDatabaseCenterPayload() {
    Log.v("messsage","load me");
    mSubscriptions.add(mDataManagerCenter.getAllDatabaseCenterPayload()
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(new Subscriber<List<CenterPayload>>() {
                @Override
                public void onCompleted() {
                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(List<CenterPayload> centerPayloads) {
                    showCenters(centerPayloads);
                }
            }));
}

public void syncCenterPayload(CenterPayload centerPayload) {
    mSubscriptions.add(mDataManagerCenter.createCenter(centerPayload)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(new Observer<SaveResponse>() {
                @Override
                public void onCompleted() {
                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(SaveResponse center) {
                    showCenterSyncResponse();
                }
            }));
}

public void deleteAndUpdateCenterPayload(int id) {
    mSubscriptions.add(mDataManagerCenter.deleteAndUpdateCenterPayloads(id)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(new Observer<List<CenterPayload>>() {
                @Override
                public void onCompleted() {
                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(List<CenterPayload> centerPayloads) {
                    showPayloadDeletedAndUpdatePayloads(centerPayloads);
                }
            }));
}

public void showCenters(List<CenterPayload> centerPayload) {
    centerPayloads = centerPayload;
}
public void showCenterSyncResponse() {
    deleteAndUpdateCenterPayload(centerPayloads
            .get(mCenterSyncIndex).getId());
}
public void showPayloadDeletedAndUpdatePayloads(List<CenterPayload> centers) {
    mCenterSyncIndex = 0;
    this.centerPayloads = centers;
}
public void syncPayload() {
    for (int i = 0; i < centerPayloads.size(); ++i) {
        if (centerPayloads.get(i).getErrorMessage() == null) {
            syncCenterPayload(centerPayloads.get(i));
            mCenterSyncIndex = i;
            break;
        } else {
            Log.v("messsage","else block");
        }
    }
}
    }

ActivityComponent

  @PerActivity
  @Component(dependencies = ApplicationComponent.class, modules = 
  ActivityModule.class)
  public interface ActivityComponent {
void inject(LoginActivity loginActivity);
void inject(PassCodeActivity passCodeActivity);
 //other  methods
void inject(SyncAdapter syncAdapter);
 }

ActivityModule

  @Module
  public class ActivityModule {

private Activity mActivity;

public ActivityModule(Activity activity) {
    mActivity = activity;
}

@Provides
Activity provideActivity() {
    return mActivity;
}

@Provides
@ActivityContext
Context providesContext() {
    return mActivity;
}
 }

РЕДАКТИРОВАТЬ SyncService.java

    public class SyncService extends Service {
private static final Object sSyncAdapterLock = new Object();
private static SyncAdapter sSyncAdapter = null;
@Override
public void onCreate() {
    synchronized (sSyncAdapterLock) {
        if (sSyncAdapter == null) {
            sSyncAdapter = new SyncAdapter(getApplicationContext(), true);
        }
    }
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return sSyncAdapter.getSyncAdapterBinder();
}
  }

Может ли кто-нибудь помочь мне заставить это работать? поскольку я не могу понять, где использовать инъекцию и как это сделать без компонента деятельности? Также будет оценен другой и лучший подход. Спасибо

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
269
1

Ответы 1

Вы можете реализовать конструктор, поэтому, пожалуйста, использовать инъекцию конструктора для инициализации вашего адаптера.

public class SyncAdapter extends AbstractThreadedSyncAdapter {
  // ...

  @Inject
  public SyncAdapter(Context context, boolean autoInitialize) { /*...*/ }
}

Затем вы просто вставляете службу, которая возвращает SyncAdapter, как и все остальное ...

public class SyncService extends Service {

    @Inject SyncAdapter syncAdapter;

    @Override
    public void onCreate() {
        AndroidInjection.inject(this);
        // or
        DaggerSyncServiceComponent.create().inject(this);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return syncAdapter;
    }
}

Вот и все.

Не удается разрешить символ AndroidInjection или DaggerSyncServiceComponent. Что мне не хватает?

Falcon 17.05.2018 10:20

@Falcon AndroidInjection предназначен для случаев, когда вы используете dagger.android, DaggerSyncServiceComponent следует заменить любым компонентом, который вы хотите использовать для внедрения своей службы. Просто введите его, как если бы вы делали свою деятельность и т. д.

David Medenjak 17.05.2018 10:32

Спасибо за ответ, попробую. Есть ли альтернативный способ сделать это без использования dagger.android в gradle, поскольку это проект с открытым исходным кодом, и я не хочу ничего ломать, и добавление dagger.android дало мне много ошибок.

Falcon 17.05.2018 12:28

@Falcon Вы можете использовать любой из ваших компонентов, чтобы внедрить его или создать для него новый, выделенный. В конце концов, вам просто нужно вызвать someComponent.inject(this), чтобы ввести поля.

David Medenjak 17.05.2018 12:30

Другие вопросы по теме