将图像保存到Android设备时,我应该使用后台线程吗?

时间:2015-02-18 16:02:14

标签: android multithreading bitmap android-asynctask

我需要从View(android.webkit.WebView)捕获一个Image并将其保存为Android设备上的PNG文件。

我应该使用AsyncTasks保存图像以避免阻止UI线程吗?

我应该从AsyncTask doInBackground方法中删除哪些代码?

代码:

    private void getWebScreenshot() {

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "IMG_" + timeStamp;
    File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
    String filePath = storageDir + "/" + imageFileName + ".png";

    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        // Log.i(LOGTAG, "External Storage Available");

        // Create the storage directory if it does not exist
        if (!storageDir.exists()) {
            // Log.i(LOGTAG,"storageDir does not exists");
            if (!storageDir.mkdirs()) {
                // Log.d(LOGTAG, "Failed to create the directory");
            }
        }

        // Create bitmap screen capture
        Bitmap bitmap;
        View sview = findViewById(R.id.web_view);
        sview.setDrawingCacheEnabled(true);
        bitmap = Bitmap.createBitmap(sview.getDrawingCache());
        sview.setDrawingCacheEnabled(false);

        FileOutputStream fout = null;
        File imageFile = new File(filePath);

        try {
            fout = new FileOutputStream(imageFile);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fout);
            fout.flush();
            fout.close();

            // Tell the media scanner about the new file so that it is
            // immediately available to the user.
            MediaScannerConnection.scanFile(this,
                    new String[]{imageFile.toString()}, null,
                    new MediaScannerConnection.OnScanCompletedListener() {
                        public void onScanCompleted(String path, Uri uri) {
                            // Log.i(LOGTAG, "ExternalStorage Scanned " + path + ":");
                            // Log.i(LOGTAG, "ExternalStorage > uri: " + uri);
                        }
                    });

            // Log.i(LOGTAG, "Success");

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

2 个答案:

答案 0 :(得分:1)

是的,绝对必须在后台线程中执行此操作。所有I / O操作都必须在后台线程上完成,因为无法保证操作完成的速度有多快 - 可能需要几毫秒到几分钟(这是一个非常糟糕的糟糕情况)。所有对存储,数据库,Web资源等的访问都必须在后台线程上完成。

使用多个线程可能会导致同步问题。仅移动到执行I / O操作的代码的单独线程。

希望这会有所帮助:)

答案 1 :(得分:1)

  1. 答案是肯定的,您不想阻止您的UI线程。 更好的解决方案是将图像保存在其他线程中,同时通知用户,这样他就会知道图像正在保存(启用按钮,加载器gif ......)。

  2. 线程中的所有内容都可以接受您采用时间戳的部分,因为您可能会意外地创建两个具有相同名称的文件