【问题标题】:How do I load an image into imageview from URL that I have gotten from JSON parse?如何从我从 JSON 解析中获得的 URL 将图像加载到 imageview 中?
【发布时间】:2013-10-17 12:24:06
【问题描述】:

我在这里查看了一些答案,但他们都提出了不同的问题。结果我想出了下面的代码。我使用 AsyncTask 解析我的 JSON,我可以在两个地方访问它。 doInBackground() 结束;和 onPostExecute();

我在两者中都尝试了以下代码,并得到了两个不同的错误:

代码:

try {
   ImageView one = (ImageView)findViewById(R.id.one);
   String getImage = bookDet.get(0).image;
   Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(getImage).getContent());
   one.setImageBitmap(bitmap); 
} catch (MalformedURLException e) {
   e.printStackTrace();
} catch (IOException e) {
   e.printStackTrace();
}

BookDet 是保存数据的 ArrayList,它已被转换为字符串并放在那里。

我尝试doInBackground()时的错误:

E/AndroidRuntime(14007): FATAL EXCEPTION: AsyncTask #2
E/AndroidRuntime(14007): java.lang.RuntimeException: An error occured while executing doInBackground()
E/AndroidRuntime(14007):    at android.os.AsyncTask$3.done(AsyncTask.java:299)
E/AndroidRuntime(14007):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
E/AndroidRuntime(14007):    at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
E/AndroidRuntime(14007):    at java.util.concurrent.FutureTask.run(FutureTask.java:239)
E/AndroidRuntime(14007):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
E/AndroidRuntime(14007):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
E/AndroidRuntime(14007):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
E/AndroidRuntime(14007):    at java.lang.Thread.run(Thread.java:856)
E/AndroidRuntime(14007): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

这只是其中的一部分,但最后一行似乎是关键。只有一个 AsyncTask,所以是的。

我在 onPostExecute 中执行此操作时出错:

E/AndroidRuntime(16801): FATAL EXCEPTION: main
E/AndroidRuntime(16801): android.os.NetworkOnMainThreadException
E/AndroidRuntime(16801):    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
E/AndroidRuntime(16801):    at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
E/AndroidRuntime(16801):    at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
E/AndroidRuntime(16801):    at java.net.InetAddress.getAllByName(InetAddress.java:214)
E/AndroidRuntime(16801):    at libcore.net.http.HttpConnection.<init>(HttpConnection.java:70)
E/AndroidRuntime(16801):    at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)
E/AndroidRuntime(16801):    at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:340)
E/AndroidRuntime(16801):    at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87)
E/AndroidRuntime(16801):    at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
E/AndroidRuntime(16801):    at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:316)
E/AndroidRuntime(16801):    at libcore.net.http.HttpEngine.connect(HttpEngine.java:311)
E/AndroidRuntime(16801):    at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
E/AndroidRuntime(16801):    at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
E/AndroidRuntime(16801):    at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81)
E/AndroidRuntime(16801):    at java.net.URLConnection.getContent(URLConnection.java:190)
E/AndroidRuntime(16801):    at java.net.URL.getContent(URL.java:447)

所以我不能在主线程中这样做......?

目前我能做的最好的事情就是有一个 TextView 将该 url 拉到一个字符串中,并且显示得很好,但这显然没用。

有什么想法吗?如何从一组异步完成的解析数据中显示图像?

感谢任何人的帮助。谢谢。

【问题讨论】:

    标签: android json asynchronous android-asynctask imageview


    【解决方案1】:

    我向您推荐一种像魅力一样工作的不同方式:Android Query。

    您可以从这里下载该 jar 文件:http://code.google.com/p/android-query/downloads/list

    AQuery androidAQuery=new AQuery(this);
    

    举个例子:

    androidAQuery.id(YOUR IMAGEVIEW).image(YOUR IMAGE TO LOAD, true, true, getDeviceWidth(), ANY DEFAULT IMAGE YOU WANT TO SHOW);
    

    使用上面的代码,您可以直接通过 url 显示您的图像。现在下面的代码是直接从url获取位图:

    androidAQuery.ajax(YOUR IMAGE URL,Bitmap.class,0,new AjaxCallback<Bitmap>(){
                            @Override
                            public void callback(String url, Bitmap object, AjaxStatus status) {
                                super.callback(url, object, status);
    
                                //You will get Bitmap from object.
                            }
    
    });
    

    这个库是 Android 自己提供的,所以使用它并查看你想要的结果。

    它非常快速和准确,使用它您可以在加载时找到更多功能,例如动画;如果需要,获取位图;等等

    【讨论】:

    • 所以我可以把它放在我的 onPostExecute 中然后它会工作吗?我不知道图片网址,它位于从 JSON 调用的字符串中。
    • 无需在 onPostExecute() 中调用它,只需从 Json 中获取您的图像 url 并将其传递到 Android Query 中即可。它将下载并显示您的图像。
    • 等等,我不明白。在 onPostExecute 中,我将其余的 JSON 数据放入 TextViews。它必须在我的 AsyncTask 中的某个地方,因为那是我可以访问 imageurl 的唯一地方,以字符串的形式。
    • 是的,然后在那里执行android查询代码,你可以使用它。获取解析后的数据后使用它。我给了你2个演示代码,一个用于下载和显示图像,另一个是从url获取位图。
    • 我似乎遇到的唯一问题是 AjaxStatus 似乎没有导入和 getDeviceWidth(),我可以用其他东西替换它吗?
    【解决方案2】:

    您应该异步获取文件,然后为您的 imageview 设置它。

    我已经大量使用这个轻量级库来简化进行异步 HTTP 调用的所有操作:http://loopj.com/android-async-http/

    例子:

    AsyncHttpClient client = new AsyncHttpClient();
    String[] allowedContentTypes = new String[] { "image/png", "image/jpeg" };
    client.get("http://example.com/file.png", new BinaryHttpResponseHandler(allowedContentTypes) {
        @Override
        public void onSuccess(byte[] fileData)
        {
             Bitmap bmp = BitmapFactory.decodeByteArray(fileData, 0, fileData.length);
    
             if(imageView != null)
             {
                 imageView.setImageBitmap(bmp);
             }
        }
    });
    

    其中 imageView 是您之前获得的 ImageView 的引用:

    imageView = (ImageView) view.findViewById(R.id.YOUR_IMAGEVIEW_ID);
    

    希望对你有帮助。

    【讨论】:

    • 有没有办法在没有库的情况下做到这一点?它的要点是什么?我可以在另一个下启动一个新的 AsyncTask 并再次提取数据但只提取图像 url 或通过另一个的 onPostExecute 吗?
    • 当然有,但是在这里只需 1 分钟的集成和很少的代码行,您就有了一个非常稳定和健壮的解决方案(顺便说一下,这个库被 Instagram 和 Pinterest 使用)。然后,如果这是您的应用程序中唯一需要进行异步 HTTP 调用的地方,我可以理解您不想集成库,所以是的,使用 AsyncTask,如下所述:stackoverflow.com/questions/13085951/…
    • 酷,我会放手的。那个已经有了 URL,在我一起解析一大块数据之前我不会得到我的。希望它仍然有效,并且我没有收到与上述相同的错误。事实上,我认为它不会起作用。
    • 当然,记得在清单中设置此权限:
    • 妈的,还是逼近吧。
    【解决方案3】:

    您必须在 doBackground() 中下载图像,然后将 doBackground 的结果设置为您刚刚下载的位图。在 onPostExecute(Bitmap bmp) 中,您可以将其设置为所需的 imageView。不要忘记更改 AsyncTask 的参数:

    AsyncTask<SomeObject, Integer, Bitmap>
    

    代码应如下所示。

    public class DownloadFilesTask extends AsyncTask<SomeObject, Integer, Bitmap> {
        protected Long doInBackground(SomeObject object) {
    
            //do the networking and parse json here
    
            try {
                String getImage = bookDet.get(0).image;
                Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(getImage).getContent()); 
                return bitmap;
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } 
            return null;
        }
    
        protected void onPostExecute(Bitmap bmp) {
    
            //set the bitmap to image here
    
            ImageView one = (ImageView)findViewById(R.id.one);
            one.setImageBitmap(bmp);
        }
    }
    

    【讨论】:

    • 我现在的 AsyncTask 是这样的: public class HttpTask extends AsyncTask> {} 所以你认为是开始一个新的还是我可以填这个一个?
    • 第一点(first Void)是doBackgorund()的输入参数点,第二点是进度变化点,第三点是onBackgroud输出和onPostExecute输入。因此,您可以创建新的 AsycTask 并针对这种情况启动此任务。对于 aech 情况,您可以有不同的 AssyncTask
    • 谢谢你,但下面的答案更容易,因为我只需要添加一行代码。我想我可以不用使用谷歌提供的小型图书馆。我会用这个加倍我的代码。可惜这种类型的东西需要一个全新的 AsyncTask,但这是有道理的。
    【解决方案4】:

    您可以使用droidQuery 大大简化此操作:

    ImageView one = (ImageView)findViewById(R.id.one);
    String getImage = bookDet.get(0).image;
    $.with(one).image(getImage);
    

    这将从 URL 延迟加载图像,并处理所有异步调用和数据解析。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-23
      相关资源
      最近更新 更多