Skip to content

Commit 34f894a

Browse files
Refactor LoadLicenseTask to use RxJava instead of AsyncTask
1 parent 70faa91 commit 34f894a

File tree

2 files changed

+161
-67
lines changed

2 files changed

+161
-67
lines changed

OpenScienceJournal/app/src/main/java/com/google/android/apps/forscience/whistlepunk/opensource/licenses/LicenseActivity.java

Lines changed: 29 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.google.android.apps.forscience.whistlepunk.opensource.licenses;
1818

1919
import android.content.Intent;
20-
import android.os.AsyncTask;
2120
import android.os.Bundle;
2221
import android.text.TextUtils;
2322
import android.util.Log;
@@ -41,21 +40,9 @@
4140
import com.google.android.apps.forscience.whistlepunk.SettingsActivity;
4241
import com.google.android.apps.forscience.whistlepunk.opensource.R;
4342

44-
import org.w3c.dom.Document;
45-
import org.w3c.dom.Node;
46-
import org.w3c.dom.NodeList;
47-
import org.xml.sax.SAXException;
48-
49-
import java.io.IOException;
50-
import java.util.ArrayList;
51-
import java.util.Collections;
5243
import java.util.Comparator;
5344
import java.util.List;
5445

55-
import javax.xml.parsers.DocumentBuilder;
56-
import javax.xml.parsers.DocumentBuilderFactory;
57-
import javax.xml.parsers.ParserConfigurationException;
58-
5946
import io.reactivex.android.schedulers.AndroidSchedulers;
6047
import io.reactivex.annotations.NonNull;
6148
import io.reactivex.observers.DisposableSingleObserver;
@@ -113,73 +100,48 @@ public boolean onOptionsItemSelected(MenuItem item) {
113100
}
114101

115102
public static class LicenseListFragment extends ListFragment {
116-
117103
private ArrayAdapter<License> adapter;
104+
private final LoadLicenseTask loadLicenseTask = new LoadLicenseTask(Schedulers.io(), AndroidSchedulers.mainThread());
118105

119-
public LicenseListFragment() {}
106+
public LicenseListFragment() {
107+
}
120108

121109
@Override
122110
public void onResume() {
123111
super.onResume();
124-
125112
setEmptyText(getActivity().getString(R.string.licenses_empty));
126113
getActivity().setTitle(R.string.settings_open_source_title);
127-
new LoadLicenseTask().execute();
114+
fetchLicenses();
128115
}
129116

130-
private List<License> getLicenses() {
131-
DocumentBuilder builder = null;
132-
List<License> licenses = new ArrayList<>();
133-
try {
134-
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
135-
Document licenseDoc = builder.parse(getResources().openRawResource(R.raw.license_list));
136-
NodeList licenseNodes = licenseDoc.getElementsByTagName(TAG_LICENSE);
137-
final int size = licenseNodes.getLength();
138-
for (int index = 0; index < size; index++) {
139-
Node licenseNode = licenseNodes.item(index);
140-
License license = new License();
141-
license.key = licenseNode.getAttributes().getNamedItem(ATTRIB_KEY).getNodeValue();
142-
Node childNode = licenseNode.getFirstChild();
143-
while (childNode != null) {
144-
String nodeName = childNode.getNodeName();
145-
String nodeValue =
146-
childNode.getFirstChild() != null ? childNode.getFirstChild().getNodeValue() : null;
147-
if (TAG_TITLE.equals(nodeName)) {
148-
license.title = nodeValue;
149-
} else if (TAG_RESOURCE.equals(nodeName)) {
150-
license.resource = nodeValue;
151-
} else if (TAG_HEADER.equals(nodeName)) {
152-
license.copyrightHeader = nodeValue;
153-
}
154-
childNode = childNode.getNextSibling();
155-
}
156-
if (license.isValid()) {
157-
licenses.add(license);
158-
} else {
159-
Log.e(TAG, "Not adding invalid license: " + license);
160-
}
161-
}
162-
} catch (ParserConfigurationException | SAXException | IOException e) {
163-
Log.e(TAG, "Could not parse license file.", e);
164-
}
165-
Collections.sort(licenses, LICENSE_COMPARATOR);
166-
return licenses;
117+
@Override
118+
public void onPause() {
119+
super.onPause();
120+
loadLicenseTask.discard();
167121
}
168122

169-
class LoadLicenseTask extends AsyncTask<Void, Void, List<License>> {
170-
171-
@Override
172-
protected List<License> doInBackground(Void... params) {
173-
return getLicenses();
174-
}
123+
private void fetchLicenses() {
124+
final LoadLicenseTask.Args args = new LoadLicenseTask.Args(
125+
getResources(),
126+
TAG_LICENSE,
127+
ATTRIB_KEY,
128+
TAG_TITLE,
129+
TAG_RESOURCE,
130+
TAG_HEADER,
131+
LICENSE_COMPARATOR
132+
);
133+
loadLicenseTask.invoke(args, new DisposableSingleObserver<List<License>>() {
134+
@Override
135+
public void onSuccess(@NonNull List<License> licenses) {
136+
adapter = new ArrayAdapter<>(requireActivity(), android.R.layout.simple_list_item_1, android.R.id.text1, licenses);
137+
setListAdapter(adapter);
138+
}
175139

176-
@Override
177-
protected void onPostExecute(List<License> licenses) {
178-
adapter =
179-
new ArrayAdapter<>(
180-
getActivity(), android.R.layout.simple_list_item_1, android.R.id.text1, licenses);
181-
setListAdapter(adapter);
182-
}
140+
@Override
141+
public void onError(@NonNull Throwable e) {
142+
Log.e("LicenseListFragment", "loadLicenseTask", e);
143+
}
144+
});
183145
}
184146

185147
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package com.google.android.apps.forscience.whistlepunk.opensource.licenses;
2+
3+
import android.content.res.Resources;
4+
import android.util.Log;
5+
6+
import androidx.annotation.NonNull;
7+
8+
import com.google.android.apps.forscience.whistlepunk.opensource.R;
9+
10+
import org.w3c.dom.Document;
11+
import org.w3c.dom.Node;
12+
import org.w3c.dom.NodeList;
13+
import org.xml.sax.SAXException;
14+
15+
import java.io.IOException;
16+
import java.util.ArrayList;
17+
import java.util.Collections;
18+
import java.util.Comparator;
19+
import java.util.List;
20+
21+
import javax.xml.parsers.DocumentBuilder;
22+
import javax.xml.parsers.DocumentBuilderFactory;
23+
import javax.xml.parsers.ParserConfigurationException;
24+
25+
import io.reactivex.Scheduler;
26+
import io.reactivex.Single;
27+
import io.reactivex.disposables.CompositeDisposable;
28+
import io.reactivex.observers.DisposableSingleObserver;
29+
30+
public class LoadLicenseTask {
31+
public static class Args {
32+
@NonNull
33+
final Resources resources;
34+
35+
@NonNull
36+
final String tag_license;
37+
38+
@NonNull
39+
final String attribute_key;
40+
41+
@NonNull
42+
final String tag_title;
43+
44+
@NonNull
45+
final String tag_resource;
46+
47+
@NonNull
48+
final String tag_header;
49+
50+
@NonNull
51+
final Comparator<LicenseActivity.License> comparator;
52+
53+
public Args(@NonNull Resources resources, @NonNull String tag_license, @NonNull String attribute_key, @NonNull String tag_title, @NonNull String tag_resource, @NonNull String tag_header, @NonNull Comparator<LicenseActivity.License> comparator) {
54+
this.resources = resources;
55+
this.tag_license = tag_license;
56+
this.attribute_key = attribute_key;
57+
this.tag_title = tag_title;
58+
this.tag_resource = tag_resource;
59+
this.tag_header = tag_header;
60+
this.comparator = comparator;
61+
}
62+
}
63+
64+
public static final String TAG = "TAG";
65+
66+
private final CompositeDisposable disposable = new CompositeDisposable();
67+
68+
private final Scheduler operationScheduler;
69+
private final Scheduler notificationScheduler;
70+
71+
public LoadLicenseTask(@NonNull Scheduler operationScheduler, @NonNull Scheduler notificationScheduler) {
72+
this.operationScheduler = operationScheduler;
73+
this.notificationScheduler = notificationScheduler;
74+
}
75+
76+
public void invoke(@NonNull Args args, @NonNull DisposableSingleObserver<List<LicenseActivity.License>> observer) {
77+
disposable.add(performOperation(args)
78+
.subscribeOn(operationScheduler)
79+
.observeOn(notificationScheduler)
80+
.subscribeWith(observer));
81+
}
82+
83+
@NonNull
84+
private Single<List<LicenseActivity.License>> performOperation(@NonNull Args args) {
85+
return getLicenses(args);
86+
}
87+
88+
private Single<List<LicenseActivity.License>> getLicenses(@NonNull Args args) {
89+
return Single.create(e -> {
90+
DocumentBuilder builder = null;
91+
List<LicenseActivity.License> licenses = new ArrayList<>();
92+
try {
93+
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
94+
Document licenseDoc = builder.parse(args.resources.openRawResource(R.raw.license_list));
95+
NodeList licenseNodes = licenseDoc.getElementsByTagName(args.tag_license);
96+
final int size = licenseNodes.getLength();
97+
for (int index = 0; index < size; index++) {
98+
Node licenseNode = licenseNodes.item(index);
99+
LicenseActivity.License license = new LicenseActivity.License();
100+
license.key = licenseNode.getAttributes().getNamedItem(args.attribute_key).getNodeValue();
101+
Node childNode = licenseNode.getFirstChild();
102+
while (childNode != null) {
103+
String nodeName = childNode.getNodeName();
104+
String nodeValue =
105+
childNode.getFirstChild() != null ? childNode.getFirstChild().getNodeValue() : null;
106+
if (args.tag_title.equals(nodeName)) {
107+
license.title = nodeValue;
108+
} else if (args.tag_resource.equals(nodeName)) {
109+
license.resource = nodeValue;
110+
} else if (args.tag_header.equals(nodeName)) {
111+
license.copyrightHeader = nodeValue;
112+
}
113+
childNode = childNode.getNextSibling();
114+
}
115+
if (license.isValid()) {
116+
licenses.add(license);
117+
} else {
118+
Log.e(TAG, "Not adding invalid license: " + license);
119+
}
120+
}
121+
} catch (ParserConfigurationException | SAXException | IOException exception) {
122+
Log.e(TAG, "Could not parse license file.", exception);
123+
}
124+
Collections.sort(licenses, args.comparator);
125+
e.onSuccess(licenses);
126+
});
127+
}
128+
129+
public void discard() {
130+
disposable.clear();
131+
}
132+
}

0 commit comments

Comments
 (0)