上传多张图片时出现 OutOfMemoryError

OutOfMemoryError while uploading multi images

我正在将多张图片一张一张地上传到服务器。我在行 bm = BitmapFactory.decodeFile(imagepath); 中收到 OOM 错误。我在上传每个图像文件后回收了位图,但仍然显示错误。我的代码有问题吗?另外,有没有更好的方法从ArrayList中一张一张上传多张图片?

 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();
            }


        }
    }

它正在崩溃,因为您一次创建了很多 AsyncTask。如果一次线程总数运行达到138,应用就会崩溃。所以你应该使用 executor 如下

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

以上将一次执行 5 个任务,然后在前一个任务完成后开始下一个任务

以下是多个异步任务的参考资料

http://blogs.innovationm.com/multiple-asynctask-in-android/

或者你可以使用一些其他的http库ion volley retrofit

我不知道出了什么问题,但我遇到了同样的问题,当我开始使用网络库而不是 asynktask 时,它就结束了。

我用的是https://github.com/koush/ion 还有Volley .

有了这个你就不需要解码了,只需要上传一个文件,你就不用担心asynktask的缺陷了。

Asynctask 不适用于长时间操作和同时进行多个异步任务,试试我的方法你会很棒

I'm uploading multiple images。但是我看到你正在上传文件。并且您首先为它们中的每一个创建一个位图。这需要大量内存。然后你压缩到一个占用更多内存的字节数组。

完全错误的做法。

您应该只上传文件的字节。取消 BitmapFactory 和中间位图。

只需从 FileInputStream 中读取循环块并将这些块写入连接的 OutputStream。

在您的情况下,您可能会添加一个新的 FileBody()。