实现长时间运行的网络操作(如上传大量照片)的本机Android方式是什么,而不必使用像RoboSpice这样的库?
我已经阅读了很多关于stackoverflow的主题,建议asynctask不适合长时间运行的操作,因为它与活动的生命周期密切相关,可能导致内存泄漏,因为android 3.2只有一个线程可供所有人使用应用程序的asynctasks。 (不确定最后一个)
如何用别的东西替换我的asynctask?
现在,我听说过处理程序,执行程序,服务以及什么不是,但我究竟如何在我的代码中实现它们以及选择哪一个?
这是我使用的asynctask的一个例子
我删除了很多代码,只是为了让您看到基本结构
public class UploadPhotosToServer extends AsyncTask<String, Void, Boolean> {
@Override
protected Boolean doInBackground(String... args) {
HashMap<String, String> params = new HashMap<String, String>();
try {
if(uploadImageToServer(id, path, params)) {
success = true;
} else {
success = false;
}
} catch (Exception e) {
e.printStackTrace();
success = false;
}
return success;
}
public boolean uploadImageToServer(int imageId, String imagePath, HashMap<String, String> params) throws Exception {
try {
JSONObject json = jsonParser.uploadImageToServer(imagePath, params);
JSONObject message = json.getJSONObject("message");
String serverResponse = message.getString("success");
if (serverResponse.contentEquals("true") {
return true;
} else {
return false;
}
} catch (JSONException e) {
e.printStackTrace();
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
这里是jsonParser.uploadImageToServer
public JSONObject uploadImageToServer(String imagePath, HashMap<String, String> params) throws Exception {
HttpResponse response;
MultipartEntityBuilder multipartEntity;
HttpPost postRequest;
HttpContext localContext;
Bitmap bitmap;
try {
// Set the http handlers
httpClient = new DefaultHttpClient();
localContext = new BasicHttpContext();
postRequest = new HttpPost(SERVER + "images");
// Send the package
multipartEntity = MultipartEntityBuilder.create();
multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("file", new FileBody(new File(imagePath)));
for (Map.Entry<String, String> entry : params.entrySet()) {
multipartEntity.addTextBody(entry.getKey(), entry.getValue());
}
postRequest.setEntity(multipartEntity.build());
// Get the response. we will deal with it in onPostExecute.
response = httpClient.execute(postRequest, localContext);
HttpEntity httpEntity = response.getEntity();
inputStream = httpEntity.getContent();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
json = sb.toString();
inputStream.close();
reader.close();
} catch (ClientProtocolException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
// Try parsing the string to a JSON object
try {
jsonObject = new JSONObject(json);
} catch (JSONException e) {
e.printStackTrace();
}
// Return JSON String
return jsonObject;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
答案 0 :(得分:3)
我认为对于一组上传,我会考虑实施IntentService。正如在链接中所解释的那样,它将处理工作线程中的意图列表,直到该列表用完为止,此时服务将再次关闭。
IntentService
的实施非常简单。基于您在上面给出的示例的示例;
public class ImageUploadIntentService extends IntentService {
public ImageUploadIntentService() {
super("ImageUploadIntentService");
}
@Override
public void onCreate() {
// Not a required implementation but you might want to setup any dependencies
// here that can be reused with each intent that the service is about to
// receive.
super.onCreate();
}
@Override
public void onHandleIntent(Intent intent) {
// Process your intent, this presumably will include data such as the local
// path of the image that you want to upload.
try {
uploadImageToServer(intent.getExtra("image_to_upload"), params);
} catch (Exception e) {
// Oh :( Consider updating any internal state here so we know the state
// of play for later
}
}
public JSONObject uploadImageToServer(String imagePath, HashMap<String, String> params) throws Exception {
// All of your upload code
}
}
然后调用服务就像它一样简单;
Intent intent = new Intent(this, ImageUploadIntentService.class)
.putExtra("image_to_upload", mImagePath);
startService(intent);
这确实给我们留下了指示上传队列进度的问题。我们可以使用ResultReceiver来解决这个问题。结果接收器为Parcelable
,因此我们可以将其与意图一起发送,以便倾听我们可能感兴趣的结果。您可以使用ResultReceiver
和合适的片段来处理Activity
进度对话框,或者如果您想要一个带进度条的持久通知,那么您可以使用Service
来托管接收器。
与使用AsyncTask
相比,它更复杂一些,但它确实为您提供了更多的灵活性,而不是附加到Activity生命周期。另一个问题是IntentService
,它仍然只会让你有一个工作线程,所以图像上传不会同时发生。但我可能会考虑将你的Bitmap JPEG压缩分解为它自己的IntentService
,然后你可以在第一个上传的时候在队列中的下一个图像上进行压缩。