问题
I am facing a problem which I don't know how to solve.
GetDataTask works fine. But when I am uploading a file, the request is sent but the response comes only after the file upload is finished! GetDataTask and UploadTask run asynchronously using AsyncTask.
Any idea why it doesn't work and why the response doesn't come back when the file is uploading.
Is there another way to realize this?
The problem is, it is supposed to run in a parallel but unfortunately they are running synchronously.
I have posted my actual source below.
Thanks in advance.
GetData Task:
private class GetDataTask extends AsyncTask<String, Void, String>{
@Override
protected void onPreExecute() {
}
@Override
protected String doInBackground(String... params) {
return NetConnection.getRecordData(mUserId, mUserPassword);
}
@Override
protected void onPostExecute(String result) {
parseJson(result);
}
}
Upload Task:
private class HttpMultipartPost extends AsyncTask<String, Integer, String>
{
TextProgressBar pb;
long totalSize;
String filePath;
@Override
protected void onPreExecute()
{
pb = (TextProgressBar) findViewById(R.id.idPBUploadProgress);
pb.setMax(100);
}
@Override
protected String doInBackground(String... arg)
{
HttpClient httpClient = new DefaultHttpClient();
HttpContext httpContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost( Utils.UPLOAD_URL );
try
{
CustomMultiPartEntity multipartContent = new CustomMultiPartEntity(new ProgressListener()
{
@Override
public void transferred(long num)
{
publishProgress((int) ((num / (float) totalSize) * 100));
//Log.v(TAG, "Progress =" + num);
}
});
// We use FileBody to transfer an file
filePath = arg[0];
multipartContent.addPart("upfile", new FileBody(new File( filePath )));
totalSize = multipartContent.getContentLength();
Log.e(TAG, "Upload file size = " + totalSize/1048576 + "MB") ;
// Send it
httpPost.setEntity(multipartContent);
HttpResponse response = httpClient.execute(httpPost, httpContext);
String serverResponse = EntityUtils.toString(response.getEntity());
return serverResponse;
}
catch (Exception e)
{
System.out.println(e);
}
return null;
}
@Override
protected void onProgressUpdate(Integer... progress)
{
pb.setProgress((int) (progress[0]));
pb.setText(progress[0] + "%");
}
@Override
protected void onPostExecute(String result)
{
Log.e(TAG, "Response =" + result);
parseResult( result, filePath );
}
}
回答1:
Ok following are the notes from the official java doc...
Order of execution
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.
SO if you invoke two AsyncTask together.. they would not be executed in parallel (exception is donut, ECLAIR and gingerbread)... You can use executeOnExecutor
to execute them in parallel...
回答2:
try like this,
package com.file.upload;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
public class CustomMultiPartEntity extends MultipartEntity{
private final ProgressListener listener;
public CustomMultiPartEntity (final ProgressListener listener)
{
super();
this.listener = listener;
}
public CustomMultiPartEntity (final HttpMultipartMode mode, final ProgressListener listener)
{
super(mode);
this.listener = listener;
}
public CustomMultiPartEntity (HttpMultipartMode mode, final String boundary, final Charset charset, final ProgressListener listener)
{
super(mode, boundary, charset);
this.listener = listener;
}
@Override
public void writeTo(final OutputStream outstream) throws IOException
{
super.writeTo(new CountingOutputStream(outstream, this.listener));
}
public static interface ProgressListener
{
void transferred(long num);
}
public static class CountingOutputStream extends FilterOutputStream
{
private final ProgressListener listener;
private long transferred;
public CountingOutputStream(final OutputStream out, final ProgressListener listener)
{
super(out);
this.listener = listener;
this.transferred = 0;
}
public void write(byte[] b, int off, int len) throws IOException
{
out.write(b, off, len);
this.transferred += len;
this.listener.transferred(this.transferred);
}
public void write(int b) throws IOException
{
out.write(b);
this.transferred++;
this.listener.transferred(this.transferred);
}
}
}
This is HttpMultipartPost .java to upload file
import java.io.File;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import com.file.upload.MyMultipartEntity.ProgressListener;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
public class HttpMultipartPost extends AsyncTask<Void, Integer, Void> {
private Context context;
private String filepath;
private HttpClient client;
private ProgressDialog pd;
private long totalSize;
private static final String url = "Your URL";
public HttpMultipartPost (Context context, String filepath) {
super();
this.context = context;
this.filepath= filepath;
}
@Override
protected void onPreExecute() {
//Set timeout parameters
int timeout = 10000;
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, timeout);
HttpConnectionParams.setSoTimeout(httpParameters, timeout);
//We'll use the DefaultHttpClient
client = new DefaultHttpClient(httpParameters);
pd = new ProgressDialog(context);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("Uploading File...");
pd.setCancelable(false);
pd.show();
}
@Override
protected Void doInBackground(Void... params) {
try {
File file = new File(filepath);
//Create the POST object
HttpPost post = new HttpPost(url);
//Create the multipart entity object and add a progress listener
//this is a our extended class so we can know the bytes that have been transfered
MultipartEntity entity = new CustomMultiPartEntity (new ProgressListener()
{
@Override
public void transferred(long num)
{
//Call the onProgressUpdate method with the percent completed
publishProgress((int) ((num / (float) totalSize) * 100));
Log.d("DEBUG", num + " - " + totalSize);
}
});
//Add the file to the content's body
ContentBody cbFile = new FileBody( file, "image/jpeg" );// change according
entity.addPart("source", cbFile);
//After adding everything we get the content's lenght
totalSize = entity.getContentLength();
//We add the entity to the post request
post.setEntity(entity);
//Execute post request
HttpResponse response = client.execute( post );
int statusCode = response.getStatusLine().getStatusCode();
if(statusCode == HttpStatus.SC_OK){
//If everything goes ok, we can get the response
String fullRes = EntityUtils.toString(response.getEntity());
Log.d("DEBUG", fullRes);
} else {
Log.d("DEBUG", "HTTP Fail, Response Code: " + statusCode);
}
} catch (ClientProtocolException e) {
// Any error related to the Http Protocol (e.g. malformed url)
e.printStackTrace();
} catch (IOException e) {
// Any IO error (e.g. File not found)
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(Integer... progress) {
//Set the pertange done in the progress dialog
pd.setProgress((int) (progress[0]));
}
@Override
protected void onPostExecute(Void result) {
//Dismiss progress dialog
pd.dismiss();
}
}
Hope this will helpful to you.
回答3:
Things work fine when I replace GetData Task by a simple thread.
new Thread( new Runnable() {
@Override
public void run() {
String res = NetConnection. getRecordData(mUserId, mUserPassword);
Log.e(TAG, res);
parseJson(res);
}
}).start();
There is something fishy with AsyncTask and I dont know why.
来源:https://stackoverflow.com/questions/15468563/network-request-doesnt-work-when-uploading-a-file