下面是我用来完成类似事情的一些代码。在我的示例中,我必须发布JSON,然后下载并解析JSON响应并将响应存储在SqLite数据库中。您需要根据您的需求调整我的代码,但这个概念很简单。解决方案基本归结为:
1)使用JsonReader自己解析Json。
2)使用FilterInputStream发布进度。
我认识到这个解决方案不使用改造,所以也许你不想使用它,但也许你会发现它有帮助。
final ProgressDialog dialog = new ProgressDialog(getActivity(), ProgressDialog.THEME_HOLO_LIGHT);
dialog.setTitle(R.string.downloading_data);
dialog.setMessage("Downloading data...");
dialog.setCanceledOnTouchOutside(false);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
if (!BuildConfig.DEBUG) {
dialog.setProgressNumberFormat(null);
}
mLoginTask = new AsyncTask<Void, Integer, Void>() {
@Override
protected Void doInBackground(Void... params) {
HttpURLConnection connection = null;
try {
byte[] request = ...; // I used a JsonWriter to write to a ByteArrayOutputStream. Since you're likely getting this from file or a GET request, this is likely not necessary.
URL url = new URL("https://example.com/endpoint");
connection = (HttpURLConnection)url.openConnection();
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
connection.setRequestProperty("Content-Length", "" + request.length);
connection.setRequestProperty("Accept","*/*");
OutputStream out = connection.getOutputStream();
out.write(request);
out.flush();
out.close();
connection.setConnectTimeout(3000);
connection.setReadTimeout(10000);
connection.connect();
Thread.sleep(2000); // I don't remember why this was necessary. Likely an exception was thrown in the next line without it, at least on slower networks.
int responseCode = connection.getResponseCode();
switch (responseCode) {
case 200:
int length = connection.getContentLength();
publishProgress(0, length);
final InputStreamReader streamReader = new InputStreamReader(new FilterInputStream(connection.getInputStream()) {
private int mTotalBytesRead;
@Override
public int read() throws IOException {
int b = super.read();
if (b > 0) {
updateProgress(1);
}
return b;
}
@Override
public int read(byte[] buffer) throws IOException {
return updateProgress(super.read(buffer));
}
@Override
public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
return updateProgress(super.read(buffer, byteOffset, byteCount));
}
@Override
public long skip(long byteCount) throws IOException {
return updateProgress(super.skip(byteCount));
}
@Override
public void mark(int readLimit) {
throw new UnsupportedOperationException();
}
@Override
public void reset() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public boolean markSupported() {
return false;
}
private int updateProgress(long numBytesRead) {
if (numBytesRead > 0) {
publishProgress(mTotalBytesRead += numBytesRead);
}
return (int)numBytesRead;
}
});
JsonReader reader = new JsonReader(streamReader);
// your code here will depend on the format of the code. It seems like you have simply an array.
reader.beginArray();
while (reader.peek() == JsonToken.BEGIN_OBJECT) {
JsonObject airport = (JsonObject) Streams.parse(reader);
// do some stuff with this airport. Perhaps create an Airport object and add it to an ArrayList.
}
return null;
default:
String response = IOUtils.toString(connection.getErrorStream());
try {
Util.showToast(JsonUtil.getString(new JSONObject(response), Constants.ERROR), Toast.LENGTH_LONG);
if (responseCode == 403) { // Forbidden
publishProgress();
}
} catch (Exception e) {
Util.showToast("Unsupported response\n" + connection.getHeaderField(null)+"\n"+response, Toast.LENGTH_LONG);
}
break;
}
} catch (UnknownHostException e) {
Util.showToast("You don't appear to be connected to the Internet.", Toast.LENGTH_LONG);
} catch (Exception e) {
if (e instanceof InterruptedIOException) {
return null;
}
Util.showToast(e.toString(), Toast.LENGTH_LONG);
Log.e("DashboardActivity", "error downloading data", e);
} finally {
if (connection != null) {
connection.disconnect();
}
}
return null;
}
@Override
protected void onPostExecute(Void result) {
dialog.cancel();
TaskUtil.synchronize(HomeFragment.this);
}
@Override
protected void onCancelled() {
dialog.cancel();
// todo: maybe you have more cleanup
}
@Override
protected void onProgressUpdate(Integer... values) {
if (values.length == 0) {
MyActivity.getCurrentActivity().showLoginInfo(true);
} else {
dialog.setProgress(values[0]);
if (values.length == 2) {
dialog.setMax(values[1]);
dialog.setIndeterminate(false);
dialog.show();
}
}
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
mLoginTask.cancel(true);
}
});
请参阅http://stackoverflow.com/a/29959083/4837089。我希望这有助于 –
@SergeyNikitin我已经看到它,但我也有点困惑 – nani