【问题标题】:AsyncTask - Am I using it right?AsyncTask - 我用对了吗?
【发布时间】:2014-01-31 22:52:26
【问题描述】:

我正在编写一个显示来自网络的随机 JPG 图像的 Android 应用。如果按下按钮,应用程序会向 http://imgur.com/random 发送 GET 请求,并从服务器的响应中将 URL 保存为字符串(参见代码)。

我使用 StrictMode.setThreadPolicy 让它工作,但使用 AsyncTask 无法做到。

我试过把.JPG地址的提取放在doInBackground中,而改变图片的实际过程放在onPostExecute中,像这样:

public class MainActivity extends Activity {

    // Page "http://imgur.com/random" redirects users to a random page;
    // After the redirect, the URL will be something like "http://imgur.com/gallery/XXXXXX";
    // Actual image is at "http://i.imgur.com/XXXXXX.jpg"
    private final String WHERE = "http://imgur.com/random";
    private ImageExtractor ie;

    private class ATask1 extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {
            // Go to WHERE and get a valid URL to a random .jpg image
            ie = new ImageExtractor();
            ie.extractImageURL(WHERE);
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            // Change the image in ImageView based on the new URL
            ImageView i = (ImageView)findViewById(R.id.imageDisplay);

            try {
                Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(ie.getImageURL()).getContent());
                i.setImageBitmap(bitmap); 
            } catch (Exception e) {
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    // Method called when the button is pressed
    public void getNewImage(View v) {
        new ATask1().execute("");
    }
    ....
}

public class ImageExtractor {

    private final String USER_AGENT = "Mozilla/5.0";
    private String imageURL;

    public void extractImageURL(String address) {
        String returnedURL;

        try {
            // Create URL object based on passed argument
            URL url = new URL(address);

            // Send GET request
            HttpURLConnection conn = (HttpURLConnection)(url.openConnection());
            conn.setRequestMethod("GET");
            conn.setRequestProperty("User-Agent", USER_AGENT);

            // Response code of the answer
            conn.getResponseCode();

            // Create and save image URL as a string
            returnedURL = conn.getURL().toString();
            imageURL = returnedURL.replace("http://imgur.com/gallery/", "http://i.imgur.com/") + ".jpg";
        }
        catch (IOException e) {

        }
    }

    // Return image URL as a string;
    // http://i.imgur.com/XXXXXX.jpg
    public String getImageURL() {
        return imageURL;
    }
}

现在,如果我按下按钮,随机 .JPG 的地址会正确存储在 imageURL 中,但之后没有任何反应。到目前为止我所做的是否正确?我是否需要为 BitmapFactory 部分创建一个新的 AsyncTask/Thread 或类似的东西?具体应该如何实现?

感谢您的帮助!

【问题讨论】:

    标签: android android-asynctask


    【解决方案1】:

    我觉得没问题。只是一件事:在doInBackground() 方法中,您将返回null - 请记住,这是您的onPostExecute() 方法将接收的参数,所以基本上String result 将为空。但在你的情况下,只要你不以错误的方式使用它,就可以了。

    回答您的问题:很难判断错误在哪里,但您处理AsyncTask 的方式对我来说似乎是正确的。你不需要声明一个新的ThreadAsyncTask 来做extractImageURL(WHERE) 的工作,毕竟AsyncTask 已经是一个Thread 并且会在后台做。我会考虑在所有AsyncTask 代码中放置几个​​Log.d() 实例以查看错误在哪里,但就结构而言,它似乎没有任何问题。

    【讨论】:

    • 我不认为说“AsyncTask is a Thread”是公平的。它是一个组件,它创建一个免费的 Thread 来做繁重的工作,但也提供了在 UI Thread 上运行东西的方法
    • 你说得对,我可能用一种非常“粗鲁”的方式来描述它。
    【解决方案2】:

    您已经掌握了一般概念,但我对此有点好奇:

    Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(ie.getImageURL()).getContent());
    

    您在 UI 线程上的 onPostExecute 中执行此操作,这看起来非常像网络请求。较新版本的 Android 将完全拒绝这样做并抛出NetworkOnMainThreadException。看来您异步执行的唯一操作是获取图像路径的请求。

    【讨论】:

    • 谢谢!我真傻。我在doInBackground 方法中移动了那条线,它就像一个魅力!
    猜你喜欢
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多