2017-02-09 4 views
3

Я загружаю несколько изображений один за другим на сервер. Я получаю ошибку OOM в строке bm = BitmapFactory.decodeFile(imagepath);. Я переработал растровое изображение после загрузки каждого файла изображения, но все же отображается ошибка. Что-то не так в моем коде? Кроме того, есть ли лучший способ загрузки нескольких изображений по одному из ArrayList?OutOfMemoryError при загрузке нескольких изображений

private void loadNext() { 
     System.out.println("sammy_reached_loadNext"); 
     if(finalImages.size()>0){ 
      System.out.println("sammys_imagelist_after: "+finalImages.size()); 
      String path = finalImages.get(0); 
      System.out.println("sammys_current_pic_path "+path); 
      new UploadSingleImage(path).execute(); 
     }else{ 
      File dir = new File(file_path); 
      if (dir.isDirectory()){ 
       String[] children = dir.list(); 
       if(children!=null){ 
        for (int i = 0; i < children.length; i++){ 
         new File(dir, children[i]).delete(); 
        } 
       } 
      } 

      pd.dismiss(); 
      Toast.makeText(getActivity(), "Upload Successful", Toast.LENGTH_SHORT).show(); 
      Intent intent = new Intent(getActivity(), AfterPostActivity.class); 
      intent.putExtra("prdid",post_id); 
      startActivity(intent); 
      getActivity().finish(); 
     } 


    } 

private class UploadSingleImage extends AsyncTask<Void, Void, String> { 

     private HttpClient httpClient; 
     private HttpPost postRequest; 
     private MultipartEntity reqEntity; 
     StringBuilder s; 
     String imagepath; 
     Bitmap bm=null; 

     UploadSingleImage(String imagepath) { 
      this.imagepath = imagepath; 
     } 

     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 

      pd.setMessage("Please wait.."); 
      pd.show(); 
     } 

     @Override 
     protected String doInBackground(Void... urls) { 
      try { 
       httpClient = new DefaultHttpClient(); 

       postRequest = new HttpPost(Utility.POSTPRODIMAGES); 

       reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); 

       reqEntity.addPart("id", new StringBody(post_id)); 
       Log.e("sammy_inParam_post_id", "******" + post_id); 

       bm = BitmapFactory.decodeFile(imagepath); 

       if (bm != null) { 
        ByteArrayOutputStream bos1 = new ByteArrayOutputStream(); 
        bm.compress(Bitmap.CompressFormat.JPEG, 100, bos1); 
        byte[] data1 = bos1.toByteArray(); 
        String imgName = "myprod.jpg"; 
        ByteArrayBody bab = new ByteArrayBody(data1, imgName); 
        reqEntity.addPart("image" , bab); 
       } 

       postRequest.setEntity(reqEntity); 
       HttpResponse response = httpClient.execute(postRequest); 
       BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8")); 
       String sResponse; 
       s = new StringBuilder(); 

       while ((sResponse = reader.readLine()) != null) { 
        s = s.append(sResponse); 
       } 
       //System.out.println("sammy_Multiupload_doinback_Response: " + s); 

      } catch (Exception e) { 
       System.out.println("sammy_multiimage_doinback_excep "+e); 
      } 

      return s.toString(); 
     } 

     @Override 
     protected void onPostExecute(String result) { 
      super.onPostExecute(result); 
      System.out.println("sammys_Multiupload_onpostexec_Response: " + result); 
      try { 
       JSONObject jObj = new JSONObject(result); 
       if (jObj.getString("ACK").equals("1")) { 
        bm.recycle(); 
        finalImages.remove(0); 
        loadNext(); 
       } 

      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 


     } 
    } 
+0

Вы добавили android: largeHeap = "true" в вашем манифесте? – Akshay

ответ

1

Это происходит сбой, потому что создает много AsyncTask в то время. Если общее количество потоков, запущенных за один раз, достигает 138, приложение будет аварийно завершено. Таким образом, вы должны использовать executor ниже

new UploadSingleImage(path).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)

выше будет выполнять 5 заданий в то время, а затем начать следующий, когда предыдущая один завершает

Ниже приводятся ссылки на несколько asynctasks

http://blogs.innovationm.com/multiple-asynctask-in-android/ https://stackoverflow.com/a/4072832/2809326

Или вы можете использовать некоторые другие http-библиотеки ionvolleyretrofit

+0

Можете ли вы показать мне код для загрузки изображений с помощью MultipartEntity в Volley. @arjun_sna –

+0

проверить это https://gist.github.com/anggadarkprince/a7c536da091f4b26bb4abf2f92926594 – arjun

+0

Я использовал ваше предложение 'AsyncTask.THREAD_POOL_EXECUTOR', а также добавил следующие строки:' BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 4; bm = BitmapFactory.decodeFile (путь к изображению, параметры); 'Теперь он работает. –

0

Я не знаю, что случилось, но у меня была такая же проблема, и все закончилось, когда я начал использовать сетевые библиотеки вместо asynktask.

Я использовал https://github.com/koush/ion и есть также Volley.

С этим вам не нужно расшифровывать, вы можете просто загрузить файл, и вам не нужно беспокоиться о дефектах asynktask.

AsyncTask не предназначен для длительных операций и нескольких asynctasks в то же время, попробуйте мой подход вы будете greatfull

0

I'm uploading multiple images. Но я вижу, что вы загружаете файлы. И сначала вы создаете растровое изображение для каждого из них. Это занимает много памяти. Затем вы сжимаете массив байтов, который занимает еще больше памяти.

Совершенно неправильный подход.

Вы должны просто загрузить байты файла. Уберите BitmapFactory и промежуточное растровое изображение.

Просто прочитайте в цикле фрагменты из FileInputStream и напишите эти фрагменты в OutputStream соединения.

В вашем случае вы, вероятно, можете добавить новый FileBody().

Смежные вопросы