2014-08-31 58 views
0

如何在不使用RoboSpice等库的情况下实现长时间运行的网络操作(如上传一大堆照片)的原生Android方式是什么?如何在不使用AsyncTask而不使用库的情况下实现长时间运行的网络上传

我已经阅读了很多关于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

AsyncTask有什么问题?它使线程的使用变得容易。 – Simas 2014-08-31 09:16:29

+0

我建议写一个'报警管理器'调用'服务'上传数据在后台线程中使用asynctask – 2014-08-31 09:23:25

+0

我已经阅读了很多关于stackoverflow的话题,建议asynctask不适合长时间运行的操作,因为它是密切相关的到一个活动的生命周期,可能会导致内存泄漏,并且由于android 3.2只有一个线程适用于应用程序的所有asynctasks。 – 2014-08-31 09:38:09

回答

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,因此我们可以将其发送给意图,以便聆听我们可能感兴趣的结果。您可以使用Activity和合适的进度对话框处理ResultReceiver,或者如果您想要持续通知一个进度条,然后您可以使用Service来托管接收器。

这比使用AsyncTask要多一点,但它确实给了你更多的灵活性,并且不像活动生命周期那样附加。另一个与IntentService陷阱,它仍然只会让你一个工作线程,因此图像上传不能同时发生。但是我可能会考虑将你的位图JPEG压缩分解为它自己的IntentService,然后当第一个被上传时,你可以在队列中的下一个图像上进行压缩。

+0

谢谢我会考虑这个并试一试! – 2014-08-31 10:25:48

+0

我是否将此服务添加到Manifest? – 2014-08-31 10:26:17

+0

是的,它就像任何其他服务一样,所以你需要继续并将其添加到你的清单。 – 2014-08-31 10:27:15

相关问题