简体   繁体   中英

How do I load an image into imageview from URL that I have gotten from JSON parse?

I've looked at a few answers on here but they all ask different things. As a result I came up with the code below. I parse my JSON using an AsyncTask I have access to it in two places. The end of doInBackground(); and onPostExecute();

I tried the following code in both and got two different errors:

The code:

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 is the ArrayList that holds the data, it has been converted to a string and put there.

The error when I try it 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.

That's only part of it but the last line seems to be the key. There's only one AsyncTask so yeah.

Error when I do it in 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)

So I can't do it in the main thread...?

The best I can do at the moment is have a TextView that pulls that url to a string and that shows up just fine but that's obviously useless.

Any ideas? How do I get the image to show up from a parsed set of data that was done Asynchronously?

Appreciate anyones help. Thanks.

I recommend you a different way that works like a charm: Android Query.

You can download that jar file from here: http://code.google.com/p/android-query/downloads/list

AQuery androidAQuery=new AQuery(this);

As an example:

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

Using above code you can directly show your Image through url. Now below code is to get Bitmap Directly from the 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.
                        }

});

This library is provided by Android itself, so use it and see the result whatever you want.

It's very fast and accurate, and using this you can find many more features like Animation when loading; getting a bitmap, if needed; etc.

You should get the file asynchronously and then set it for your imageview.

I have used a lot this lightweight library to ease all the operations of making async HTTP calls: http://loopj.com/android-async-http/ .

Example:

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);
         }
    }
});

Where imageView is a reference of your ImageView that you have previously got with:

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

Hope it helps.

you have to download the image in doBackground() and then set the result of doBackground as a Bitmap you have just downloaded. In onPostExecute(Bitmap bmp), you can set it to the desired imageView. Do not forget to change parameters of AsyncTask:

AsyncTask<SomeObject, Integer, Bitmap>

Code should look like this.

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);
    }
}

You can use droidQuery to greatly simplify this:

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

This will lazy load the image from the URL, and handle all asynchronous calls and data parsing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM