Android 如何从JSON解析得到的URL将图像加载到imageview中?

Android 如何从JSON解析得到的URL将图像加载到imageview中?,android,json,asynchronous,android-asynctask,imageview,Android,Json,Asynchronous,Android Asynctask,Imageview,我在这里看过一些答案,但它们都问不同的问题。因此,我想出了下面的代码。我使用AsyncTask解析JSON,我可以在两个地方访问它。doInBackground的结束;和onPostExecute 我在这两个版本中都尝试了以下代码,但出现了两个不同的错误: 守则: try { ImageView one = (ImageView)findViewById(R.id.one); String getImage = bookDet.get(0).image; Bitmap bitm

我在这里看过一些答案,但它们都问不同的问题。因此,我想出了下面的代码。我使用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,它已转换为字符串并放在那里

在后台尝试时出现的错误:

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.
这只是其中的一部分,但最后一行似乎是关键。只有一个任务,所以是的

在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)
所以我不能在主线程中执行

目前我所能做的最好的事情就是使用一个文本视图,将url拉到一个字符串中,结果显示得很好,但这显然是无用的

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


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

您应该异步获取文件,然后将其设置为imageview

我使用了很多这个轻量级库来简化进行异步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);

希望有帮助。

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

我使用了很多这个轻量级库来简化进行异步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);

希望它能有所帮助。

我向您推荐一种不同的方式,它就像一个魔咒:Android查询

您可以从此处下载该jar文件:

例如:

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本身提供的,所以使用它并查看结果


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

我建议您使用另一种类似于魅力的方式:Android查询

您可以从此处下载该jar文件:

例如:

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本身提供的,所以使用它并查看结果


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

您必须在doBackground中下载图像,然后将doBackground的结果设置为刚刚下载的位图。在onPostExecuteBitmap 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);
    }
}

您必须在doBackground中下载图像,然后将doBackground的结果设置为刚刚下载的位图。在onPostExecuteBitmap 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);
    }
}
您可以使用来大大简化此过程:

ImageView one = (ImageView)findViewById(R.id.one);
String getImage = bookDet.get(0).image;
$.with(one).image(getImage);
这将从URL延迟加载图像,并处理所有异步调用和数据解析。

您可以使用它来大大简化这一过程:

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

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

有没有一种方法可以在没有库的情况下实现这一点?要点是什么?我可以在另一个任务下启动一个新的AsyncTask,然后再次拉取数据,但只拉取图像url或通过另一个的onPostExecute吗?当然可以,但在这里,通过1分钟的集成和很少的代码行,您就有了一个非常稳定和健壮的解决方案。顺便说一句,Instagram和Pinterest使用了这个库。然后,如果这是你的应用程序中唯一需要进行异步HTTP调用的地方,我可以理解你不想集成库,所以,是的,使用异步任务,正如这里所解释的:酷,我同意。不过,这一个已经有了URL,在我将一大块数据解析到一起之前,我不会得到我的URL。希望它仍然有效,我不会得到与上面相同的错误。事实上,从这个角度看,我不认为它会起作用。当然,记得在你的清单中设置了这个权限:妈的,仍然有一个力接近。有没有办法不用库就可以做到这一点?要点是什么?我可以在另一个任务下启动一个新的AsyncTask,然后再次拉取数据,但只拉取图像url或通过另一个的onPostExecute吗?当然可以,但在这里,通过1分钟的集成和很少的代码行,您就有了一个非常稳定和健壮的解决方案。顺便说一句,Instagram和Pinterest使用了这个库。然后,如果这是应用程序中唯一需要进行异步HTTP调用的地方,

我可以理解你不想集成一个库,所以是的,使用一个异步任务,正如这里所解释的:酷,我就这么做。不过,这一个已经有了URL,在我将一大块数据解析到一起之前,我不会得到我的URL。希望它仍然有效,我不会得到与上面相同的错误。事实上,我不认为它会起作用。当然,记得在你的清单中设置了这个权限:该死,仍然有一个强制关闭。所以我可以把它扔到我的onPostExecute中,然后它会起作用吗?我不知道图像url,它位于一个从JSON调用的字符串中。无需在onPostExecute中调用它,只需从JSON获取yur图像url并在Android查询中将其传递到这里。它将下载并显示你的图像。等等,我不明白。在onPostExecute中,我将剩余的JSON数据放入TextView中。它必须在我的AsyncTask中的某个地方,因为那是我唯一可以访问imageurl的地方,以字符串的形式。是的,然后在那里执行android查询代码,你可以使用它。获取解析数据后,使用它。我给了你2个演示代码,一个用于下载和显示图像,另一个用于从url获取位图。我唯一的问题是AjaxStatus似乎没有导入和获取DeviceWidth,我可以用其他东西替换它吗?所以我可以在onPostExecute中丢弃它,然后它就可以工作了?我不知道图像url,它位于一个从JSON调用的字符串中。无需在onPostExecute中调用它,只需从JSON获取yur图像url并在Android查询中将其传递到这里。它将下载并显示你的图像。等等,我不明白。在onPostExecute中,我将剩余的JSON数据放入TextView中。它必须在我的AsyncTask中的某个地方,因为那是我唯一可以访问imageurl的地方,以字符串的形式。是的,然后在那里执行android查询代码,你可以使用它。获取解析数据后,使用它。我给了你2个演示代码,一个用于下载和显示图像,另一个用于从url获取位图。我唯一的问题是AjaxStatus似乎没有导入和获取DeviceWidth,我可以用其他东西替换它吗?我当前的AsyncTask是这样的:公共类HttpTask扩展AsyncTask{}那么你认为开始一个新的还是我可以填补这个空白?第一个空白点第一个空白点是DoBackgound的输入参数,第二个是进度更改点,第三个空白点是OnBackground输出和onPostExecute输入点。因此,您可以创建新的AsycTask,并针对这种情况启动此AsycTask。对于aech情况,您可以使用不同的AssyncTask谢谢,但是下面的答案更简单,因为我只需要添加一行代码。我想我可以使用谷歌提供的一个小图书馆。我会用这个加倍我的代码。遗憾的是,这种类型的东西需要一个全新的AsyncTask,但这是有道理的。我当前的AsyncTask是这样的:公共类HttpTask扩展了AsyncTask{}那么你认为启动一个新的还是我可以填补这个空白?第一个空白点第一个空白点是doBackgorund的输入参数的空白点,第二个点用于进度更改,第三个点用于OnBackground输出和onPostExecute输入。因此,您可以创建新的AsycTask,并针对这种情况启动此AsycTask。对于aech情况,您可以使用不同的AssyncTask谢谢,但是下面的答案更简单,因为我只需要添加一行代码。我想我可以使用谷歌提供的一个小图书馆。我会用这个加倍我的代码。遗憾的是,这类东西需要一个全新的AsyncTask,但为什么呢。