0

我正在尝试从服务器获取图像并将该文件用作我的应用程序的背景。我已经知道我应该使用 AsyncTask 来执行此操作,但是当我运行它时,我的应用程序仍然崩溃或冻结。

这是我使用的代码:

要调用 AsyncTask:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Intent BG = new Intent((Intent) DownloadBGTask.THREAD_POOL_EXECUTOR);

异步任务:

import java.net.URL;

import com.pxr.tutorial.json.Getbackground;

import android.os.AsyncTask;

public class DownloadBGTask extends AsyncTask<URL, Integer, Long> {
    protected Long doInBackground(URL... urls) {
        int count = urls.length;
        long totalSize = 0;
        for (int i = 0; i < count; i++) {
            totalSize += Getbackground.downloadFile(urls[i]);
            publishProgress((int) ((i / (float) count) * 100));
            // Escape early if cancel() is called
            if (isCancelled()) break;
        }
        return totalSize;
    }

    protected void onProgressUpdate(Integer... progress) {
        // Things to be done while execution of long running operation
    }

    protected void onPostExecute(Long result) {
        // xecution of result of Long time consuming operation
    }
}

和 Getbackground.java:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;

import android.os.Environment;

public class Getbackground {
    URL url;

    public static long downloadFile(URL url2) {
    try {

        URL url = new URL ("http://oranjelan.nl/oranjelan-bg.png");
        InputStream input = url.openStream();{
        try {

            File fileOnSD=Environment.getExternalStorageDirectory();    
            String storagePath = fileOnSD.getAbsolutePath();
            OutputStream output = new FileOutputStream (storagePath + "/oranjelangbg.png");
                try {

                    byte[] buffer = new byte[1000000];
                    int bytesRead = 0;
                    while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) {
                    output.write(buffer, 0, bytesRead);
                    }
                    } finally {
            output.close();
            }
            } catch (IOException e) {
            throw new RuntimeException(e);
    } finally {
        try {
            input.close();
            } catch (IOException e) {
            throw new RuntimeException(e);
     }
   }    
 }    
        } catch (MalformedURLException ex) {
         throw new RuntimeException(ex);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }

        return 0;
    }
}

PS,对于糟糕的代码,我很抱歉,我对此真的很陌生,所以如果那里有一些非常愚蠢的错误,请不要感到惊讶。

4

2 回答 2

3

由于您的评论说它挂在这条线上:

Intent BG = new Intent((Intent) DownloadBGTask.THREAD_POOL_EXECUTOR);

让我们开始吧。

由于听起来您可能是新手(这并不丢脸!),我猜您不一定需要并行执行此任务。

如果您阅读 AsyncTask 上的 Android 文档,他们会试图引导您远离这种情况:

执行顺序

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

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

因此,如果您只想将 url 或 url 列表传递给任务以按顺序(系列)执行,那么只需像这样开始您的任务:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    DownloadBGTask downloader = new DownloadBGTask();
    downloader.execute(new URL("http://www.google.com"), 
                       new URL("http://stackoverflow.com"));

其中字符串是您要检索的 URL(可以是 1 个或多个)。execute()传递给任务方法的参数doInBackground()


编辑:现在您似乎已经完成了启动任务,这里有一些其他建议:

  1. 1000000 字节对我来说似乎是一个很大的缓冲区。我并不是说它不起作用,但我通常使用类似byte[1024].

  2. 关于存储下载的目录。这是我喜欢使用的代码:

private File mDownloadRootDir;
private Context mParent;        // usually this is set to the Activity using this code

private void callMeBeforeDownloading() {
    // http://developer.android.com/guide/topics/data/data-storage.html#filesExternal
    mDownloadRootDir = new File(Environment.getExternalStorageDirectory(),
        "/Android/data/" + mParent.getPackageName() + "/files/");
    if (!mDownloadRootDir.isDirectory()) {
        // this must be the first time we've attempted to download files, so create the proper external directories
        mDownloadRootDir.mkdirs();
    }
}

然后

storagePath = mDownloadRootDir.getAbsolutePath();
于 2012-07-09T09:58:22.507 回答
1

使用这个实用方法在 GetBackground 类中从 Web 下载图像:

// Utiliy method to download image from the internet
    static private Bitmap downloadBitmap(String url) throws IOException {
        HttpUriRequest request = new HttpGet(url.toString());
        HttpClient httpClient = new DefaultHttpClient();
        HttpResponse response = httpClient.execute(request);

        StatusLine statusLine = response.getStatusLine();
        int statusCode = statusLine.getStatusCode();
        if (statusCode == 200) {
            HttpEntity entity = response.getEntity();
            byte[] bytes = EntityUtils.toByteArray(entity);

            Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0,
                    bytes.length);
            return bitmap;
        } else {
            throw new IOException("Download failed, HTTP response code "
                    + statusCode + " - " + statusLine.getReasonPhrase());
        }
    }

和你的 DownloadBGTask extends AsyncTask<URL, Integer, Bitmap>

URL url = new URL ("http://oranjelan.nl/oranjelan-bg.png");
DownloadBGTask task = new DownloadBGTask(); 
task.execute(url);
于 2012-07-09T09:19:38.330 回答