Search code examples
javaandroidalarmmanagerjobservice

Avoid implementing method twice (Classes already extending abstract classes)


I have a Plugin.java class where I define two methods, one to use a JobScheduler (if API >= 21), and other to use an AlarmManager (if API < 21).

@Override
public void onCreate() {
    super.onCreate();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        scheduleDeleteJobScheduler(...);
    } else {
        scheduleDeleteAlarmManager(...);
    }
}

The scheduleDeleteJobScheduler() method uses a JobService to delete some old entries I have in a database.

public class ScheduleDeleteService extends JobService {

    @Override
    public boolean onStartJob(JobParameters params) {
        deleteOldEntries();
        jobFinished(params, false);
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return false;
    }

    public void deleteOldEntries(){...}
}

The scheduleDeleteAlarmManager() method uses a BroadcastReceiver to do the same as the JobService.

public class ScheduleDeleteReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        deleteOldEntries();
    }

    public void deleteOldEntries(){...}
}

Both classes call a deleteOldEntries() method to delete old entries from a database. This method is equal for both (JobService and BroadcastReceiver). What I want to do it's to avoid having two methods with an equal implementation.

  • Since I cannot use an Abstract or Super classes because I'm already extending the JobService and BroadcastReceiver. I know that Java doesn't allow me to extend multiple classes because it will result in the "Diamond Problem" where the compiler can't decide which superclass method to use.
  • And by using an Interface, I can only declare the method without an implementation (method signature).
  • I know that I can use static and Default methods (using an Interface), but they were introduced in Java 8 (Android Nougat - API 24). So if I used them, the entire logic of using a JobScheduler (API >= 21) and AlarmManager (API < 21) would make no sense.

I could have another class implementing the method and just call it from both ScheduleDeleteService (JobService) and ScheduleDeleteReceiver (BroadCastReceiver) classes, but I would like some advice to help me to make a better implementation.


Solution

  • As we can find in Abstract Methods and Classes:

    Consider using abstract classes if any of these statements apply to your situation:

    • You want to share code among several closely related classes.
    • ...

    First, I implemented the ScheduleDelete Abstract Class:

    abstract class ScheduleDelete {
        public void deleteOldEntries(){ ... }
    }
    

    After, inside ScheduleDeleteService class I called the ScheduleDelete#deleteOldEntries() method:

    public class ScheduleDeleteService extends JobService {
    
        @Override
        public boolean onStartJob(JobParameters params) {
            (new ScheduleDelete(){}).deleteOldEntries();
            jobFinished(params, false);
            return false;
        }
    
        @Override
        public boolean onStopJob(JobParameters params) {
            return false;
        }
    }
    

    And inside the ScheduleDeleteReceiver class I called the ScheduleDelete#deleteOldEntries() method:

    public class ScheduleDeleteReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            (new ScheduleDelete(){}).deleteOldEntries();
        }
    }