1
\$\begingroup\$

I have this class hierarchy. I want to apply generics to it but don't know how to do. AddWikiTask, ScanTask and RescanTask are subclasses of AbstractWorkerTask. DictionaryScanner has 3 functions to check if all tasks finish. How to prevent duplicate code in 3 those functions?

This is class hierarchy

    public abstract class AbstractWorkerTask<Params, Progress, Result>
    extends AsyncTask<Params, Progress, Result>
    implements Workable {
    ...}

    class AddWikiTask extends AbstractWorkerTask<String, Void, Pair<Integer, Dictionary>> {
    ...}

    class ScanTask extends AbstractWorkerTask<DictionaryBean, Void, Pair<Integer, Dictionary>> {
    ...}

    class RescanTask extends AbstractWorkerTask<DictionaryInformation, Void, Pair<Integer, Dictionary>> {
    ...}

This is DictionaryScanner.

public final class DictionaryScanner { 
    private final List<RescanTask> rescanTasks = new ArrayList<RescanTask>();
    private final List<ScanTask> scanTasks = new ArrayList<ScanTask>();
    private final List<AddWikiTask> wikiTasks = new ArrayList<AddWikiTask>();

        public boolean didAllRescanTasksFinish() {
            for (final RescanTask task : rescanTasks) {
                if (task.isWorking()) {
                    return false;
                }
            }
            return true;
        }

        public boolean didAllAddWikiTasksFinish() {
            for (final AddWikiTask task : wikiTasks) {
                if (task.isWorking()) {
                    return false;
                }
            }
            return true;
        }

        public boolean didAllScanTasksFinish() {
            for (final ScanTask task : scanTasks) {
                if (task.isWorking()) {
                    return false;
                }
            }
            return true;
        }
}

Edit: And apply generic for this. It's too long. I really don't know how to refactor it.

private void setOnPreExecuteForAddWikiTask(final AddWikiTask task, final ProgressDialog progressDialog) {
    task.setOnPreExecuteListener(new OnPreExecuteListener() {
        @Override
        public void onPreExecute() {
            if (didAllAddWikiTasksFinish()) {
                progressDialog.show();
            }
        }
    });
}

private void setOnPreExecuteForRescanTask(final RescanTask task, final ProgressDialog progressDialog) {
    task.setOnPreExecuteListener(new OnPreExecuteListener() {
        @Override
        public void onPreExecute() {
            if (didAllRescanTasksFinish()) {
                progressDialog.show();
            }
        }
    });
}

private void setOnPreExecuteForScanTask(final ScanTask task) {
    task.setOnPreExecuteListener(new OnPreExecuteListener() {
        @Override
        public void onPreExecute() {
            if (didAllScanTasksFinish() && progressBar != null) {
                progressBar.setVisibility(ProgressBar.VISIBLE);
            }
        }
    });
}

If the snippet is not elaborate enough, please let me know.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

You can take the common code in the functions in DictionaryScanner out into a common method:

    public boolean didAllRescanTasksFinish() {
        didAllXTasksFinish(rescanTasks);
    }

    private boolean didAllXTasksFinish(List<AbstractWorkerTask> tasks) {
        for (final AbstractWorkerTask task : tasks) {
            if (task.isWorking()) {
                return false;
            }
        }
        return true;
    }

Otherwise your second block of code is about as simple as you can get, because each listener has different content. If you try to remove the boilerplate you will find it gets much more difficult to understand.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.