yigit / android-priority-jobqueue

A Job Queue specifically written for Android to easily schedule jobs (tasks) that run in the background, improving UX and application stability.
3.4k stars 395 forks source link

Inject some DI into Job class #343

Open pishguy opened 7 years ago

pishguy commented 7 years ago

Hi, i can use DI in my project with your youtube tutorial, but i can't use GithubService in some jobs class extends Job and i get NULL

for example:

public class GetLatestRepositories extends Job {
    @Inject
    GithubService githubService;

    private Call<List<GithubRepo>> repositoryCall;

    public GetLatestRepositories() {
        super(new Params(Priority.MID).requireNetwork().persist());
        repositoryCall = githubService.getAllRepositories();

    }

    @Override
    public void onAdded() {
        ...
    }

    @Override
    public void onRun() throws Throwable {
        ...
    }

    @Override
    protected void onCancel(int cancelReason, @Nullable Throwable throwable) {
    }

    @Override
    protected RetryConstraint shouldReRunOnThrowable(@NonNull Throwable throwable, int runCount, int maxRunCount) {
        ...
    }
}

GithubApplicationComponent class :

@GithubApplicationScope
@Component(modules = {GithubServiceModule.class, PicassoModule.class, JobManagerModule.class, ActivityModule.class})
public interface GithubApplicationComponent {
    Picasso getPicasso();
    GithubService getGithubService();
    JobManager getJobManager();
}

MyJobService class:

public class MyJobService extends FrameworkJobSchedulerService {
    @Inject
    JobManager jobManager;

    @NonNull
    @Override
    protected JobManager getJobManager() {
        return jobManager;
    }
}

ActivityRegisterModule class:

@Module
public class ActivityRegisterModule {

    private final ActivityRegister activityRegister;

    public ActivityRegisterModule(ActivityRegister mActivityRegister) {
        activityRegister = mActivityRegister;
    }

    @Provides
    @ActivityRegisterScope
    public ActivityRegister activityRegister() {
        return activityRegister;
    }
}

and then ActivityRegister use this injection:

public class ActivityRegister extends BaseActivities {

    @Inject
    GithubService githubService;

    @Inject
    JobManager jobManager;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        ...
        component = DaggerApplicationComponent.builder()
                .githubApplicationComponent(Alachiq.get(this).getComponent())
                .build();

        component.injectActivityRegister(this);
        ...
        getRepositories();
}
private void getRepositories() {
    jobManager.addJobInBackground(getLatestRepositories);
}
yigit commented 7 years ago

can you share how you are initializing your JobManager? Are you passing the DI callback into the configuration?

pishguy commented 7 years ago

@yigit it seems my initializing JobManager is not correct sir,

my project parts is on gist:

MyJobService

JobManagerModule

GithubApplicationComponent

GetLatestRepositories

I'm trying to use GetLatestRepositories class as Job on activityregister

problem is i get NULL for

    @Inject
    GithubService githubService;

in GetLatestRepositories file

could you please see my other project files on the same gist link as this link ?

yigit commented 7 years ago

you must provide a dependency injector: https://github.com/yigit/android-priority-jobqueue/wiki/Job-Manager-Configuration

If you are using Dagger1, it is easy since it does runtime resolution. If you are using Dagger2, you probably need an interface like this:

interface Injectable {
   inject(AppComponent component);
}
class MyJob extends Job implements Injectable {
    @Override
    public void inject(AppComponent component) {
         component.inject(this);
    }
}

And your job would need to implement it + your dependency injector needs to do something like:

if (job instanceof Injectable) {
    ((Injectable) job).inject(appComponent);
}
yigit commented 7 years ago

also, if the job is persistable, don't forget to mark injected fields transient.

pishguy commented 7 years ago

@yigit

could you help whats your mean about this sentence?

And your job would need to implement it + your dependency injector needs to do something like:

if (job instanceof Injectable) { ((Injectable) job).inject(appComponent); }

whitch file is your mean?

yigit commented 7 years ago

sorry i just wrote pseudo code so just fix it to be valid java. Here is the javadoc for the dependency injection: http://yigit.github.io/android-priority-jobqueue/javadoc/com/birbit/android/jobqueue/config/Configuration.Builder.html#injector-com.birbit.android.jobqueue.di.DependencyInjector-

sorry i don't have a dagger2 example i can share nor i have time to create now but the idea above works fine.

pishguy commented 7 years ago

@yigit

thanks. could you more description about this part of your post:

https://github.com/yigit/android-priority-jobqueue/issues/343#issuecomment-293472664

is this correct:

@ActivitiesScope
@Component(dependencies = GithubApplicationComponent.class)
public interface ApplicationComponent {
    void inject(ActivityRegister activityRegister);

    void inject(ActivityStartUpApplication activityStartUpApplication);

    void inject(GetLatestRepositories getLatestRepositories);
}
pishguy commented 7 years ago

@yigit unfortunately i get null again sir:

Attempt to invoke interface method 'retrofit2.Call ir.app.myapp.NetWork.GithubService.getAllRepositories()' on a null object reference

yigit commented 7 years ago

you need to add an inject method for each Job into your ApplicationComponent class. Then each job needs to implement inject and call applicationComponent.inject(this) then last but not least, the DependencyInjection callback you've provided in the configuration builder will call job.inject(appComponent). thats why we've created that interface.

yigit commented 7 years ago

did you add the dependency injection callback to your job manager configuration?

pishguy commented 7 years ago

i change ApplicationComponent to:

@ActivitiesScope
@Component(dependencies = GithubApplicationComponent.class)
public interface ApplicationComponent {
    void inject(ActivityRegister activityRegister);
    void inject(ActivityStartUpApplication activityStartUpApplication);
    void inject(GetLatestRepositories getLatestRepositories);
}

my JobManagerModule have this configuration

it is not correct?

yigit commented 7 years ago

please take a look at this: http://yigit.github.io/android-priority-jobqueue/javadoc/com/birbit/android/jobqueue/config/Configuration.Builder.html#injector-com.birbit.android.jobqueue.di.DependencyInjector-

your configuration does not specify a dependency injection callback. Also, I've mentioned that you need to make your jobs injectable which you've not done either.

So please first apply the comments above and it will work. Sorry but I really don't have time to check your code.

adityaladwa commented 7 years ago

Even I'm not getting how to inject dependencies into a Job. Can you write an example for Dagger 2

pishguy commented 7 years ago

@LadwaAditya here you are