上传多个图片时出现OutOfMemoryError错误

3

我正在逐个上传多张图片到服务器。在这行代码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();
            }


        }
    }

你在清单文件中添加了android:largeHeap="true"吗? - Akshay
3个回答

1
由于您同时创建了大量的AsyncTask,导致应用程序崩溃。如果同时运行的线程总数达到138个,应用程序将崩溃。因此,您应该按照以下方式使用executornew UploadSingleImage(path).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) 以上代码将同时执行5个任务,然后在前一个任务完成后开始执行下一个任务。
以下是多个异步任务的参考资料。

http://blogs.innovationm.com/multiple-asynctask-in-android/ https://dev59.com/Fm855IYBdhLWcg3w7pGg#4072832

或者您可以使用其他的http库:ionvolleyretrofit


你能展示一下使用Volley中的MultipartEntity上传图片的代码吗?@arjun_sna - Somnath Pal
请查看此链接 https://gist.github.com/anggadarkprince/a7c536da091f4b26bb4abf2f92926594 - arjun
我使用了你的建议 AsyncTask.THREAD_POOL_EXECUTOR 并且添加了下面这几行代码:BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 4; bm = BitmapFactory.decodeFile(imagepath,options); 现在它能够正常工作了。 - Somnath Pal

0

我不知道出了什么问题,但我曾经遇到过同样的问题,当我开始使用网络库而不是asynktask时,问题就解决了。

我使用了https://github.com/koush/ion,还有Volley。

使用这个方法,您无需解码,只需上传文件即可,而且您无需担心asynktask的缺陷。

Asynctask不适用于长时间操作和同时进行多个asynctask,请尝试我的方法,您会感激不尽。


0

我正在上传多个图像。但是我看到你正在上传文件。而且你首先为每个文件创建位图。这需要大量的内存。然后你又将其压缩成字节数组,这需要更多的内存。

完全错误的方法。

你应该只上传文件的字节。放弃BitmapFactory和中间位图。

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接