1

我正在开发一个 Android 应用程序来从我的网络服务器下载图像。所有代码都运行良好。我正在使用 Asynctask 将图像下载到我的 SD 卡。

我的连接速度为 4mbps,但我的应用程序需要大约 8 分钟才能下载 3 张图像 (2.5 MB)。我已经阅读了 Asynctask 自动管理线程创建的其他地方,那么现在我可以做些什么来实现并发?

我在下面发布我的代码。下面的代码用于我的 Asynctask 活动,该活动将图像从服务器下载到 sdcard。

public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private String url;
Bitmap bitmap1;
String sdCard;
private final WeakReference<ImageView> imageViewReference;

public BitmapDownloaderTask(ImageView imageView) {
    imageViewReference = new WeakReference<ImageView>(imageView);
}

@Override
// Actual download method, run in the task thread
protected Bitmap doInBackground(String... params) {

    // params comes from the execute() call: params[0] is the url.
    bitmap1 = downloadBitmap(params[0]);

    boolean avail = isMemorySizeAvailableAndroid(bitmap1.getRowBytes(),
            Environment.isExternalStorageEmulated());
    if (avail) {
        try {
            sdCard = Environment.getExternalStorageDirectory().toString()
                    + "/MyCatalogue";
            File f1 = new File(sdCard);
            if (!f1.exists()) {
                f1.mkdirs();
            }
            String filename1 = params[0].substring(params[0]
                    .lastIndexOf("/") + 1);
            File file1 = new File(f1.toString(), filename1);

            OutputStream stream1 = new FileOutputStream(file1);
            bitmap1.compress(CompressFormat.JPEG, 100, stream1);
            Log.w("Abhishek", "card is " + sdCard);
        } catch (Exception e) {
            e.printStackTrace();

        }
    }
    Log.w("ImageDownloader", "Success bitmap is" + bitmap1);
    return downloadBitmap(params[0]);
}

protected static boolean isMemorySizeAvailableAndroid(long download_bytes,
        boolean isExternalMemory) {
    boolean isMemoryAvailable = false;
    long freeSpace = 0;

    // if isExternalMemory get true to calculate external SD card available
    // size
    if (isExternalMemory) {
        try {
            StatFs stat = new StatFs(Environment
                    .getExternalStorageDirectory().getPath());
            freeSpace = (long) stat.getAvailableBlocks()
                    * (long) stat.getBlockSize();
            if (freeSpace > download_bytes) {
                isMemoryAvailable = true;
            } else {
                isMemoryAvailable = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            isMemoryAvailable = false;
        }
    } else {
        // find phone available size
        try {
            StatFs stat = new StatFs(Environment.getDataDirectory()
                    .getPath());
            freeSpace = (long) stat.getAvailableBlocks()
                    * (long) stat.getBlockSize();
            if (freeSpace > download_bytes) {
                isMemoryAvailable = true;
            } else {
                isMemoryAvailable = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            isMemoryAvailable = false;
        }
    }

    return isMemoryAvailable;
}

@Override
// Once the image is downloaded, associates it to the imageView
protected void onPostExecute(Bitmap bitmap) {
    if (isCancelled()) {
        bitmap = null;
    }

    if (imageViewReference != null) {
        ImageView imageView = imageViewReference.get();
        if (imageView != null) {
            imageView.setImageBitmap(bitmap);
        }
    }
}

static Bitmap downloadBitmap(String url) {
    final AndroidHttpClient client = AndroidHttpClient
            .newInstance("Android");
    final HttpGet getRequest = new HttpGet(url);

    try {
        HttpResponse response = client.execute(getRequest);
        final int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != HttpStatus.SC_OK) {
            Log.w("ImageDownloader", "Error " + statusCode
                    + " while retrieving bitmap from " + url);
            return null;
        } else {
            Log.w("ImageDownloader", "Success " + statusCode
                    + " while retrieving bitmap from " + url);
        }

        final HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream inputStream = null;
            try {
                inputStream = entity.getContent();
                final Bitmap bitmap = BitmapFactory
                        .decodeStream(inputStream);
                return bitmap;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                entity.consumeContent();
            }
        }
    } catch (Exception e) {
        // Could provide a more explicit error message for IOException or
        // IllegalStateException
        getRequest.abort();
        Log.w("ImageDownloader", "Error while retrieving bitmap from "
                + url);
    } finally {
        if (client != null) {
            client.close();
        }
    }
    return null;
}
}
4

2 回答 2

1

为什么你在 doInBackground() 开始和结束时两次下载图像?您可以直接返回刚刚下载的位图。

如果您的最低 sdk 级别 >= 11,您可以使用参数“THREAD_POOL_EXECUTOR”调用 AsyncTask 的 executeOnExecutor 以实现并发。

如果你的 min sdk level < 11,你可以参考 AsyncTask 的源代码来实现 AsyncTask 新 API。

于 2013-08-16T05:24:01.370 回答
0

使用 executeOnExecutor

http://developer.android.com/reference/java/util/concurrent/Executor.html

 new BitmapDownloaderTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "your urls"); 

从文档中引用

http://developer.android.com/reference/android/os/AsyncTask.html

首次引入时,AsyncTask 在单个后台线程上串行执行。从 DONUT 开始,这被更改为允许多个任务并行运行的线程池。从 HONEYCOMB 开始,任务在单个线程上执行,以避免并行执行导致的常见应用程序错误。

如果你真的想要并行执行,你可以使用 THREAD_POOL_EXECUTOR 调用 executeOnExecutor(java.util.concurrent.Executor, Object[])。

于 2013-08-16T05:27:06.007 回答