RStack
RStack

Reputation: 230

Download and Display Image from url in json in Android

I am trying to display user details in recycler view.

When i try to display my image it is not working.I have tried all possibilities. Following is my adapter class.

 public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
   private LinkedList<HashMap<String, Object>> myDataSet;
   Bitmap bitmap;
   MyAdapter.ViewHolder viewHolder;
   String image;

public MyAdapter(LinkedList<HashMap<String, Object>> values) {
    myDataSet = values;
}

public class ViewHolder extends RecyclerView.ViewHolder{

    public TextView userIdView;
    public TextView jobTitleNameView;
    public TextView employeeCodeView;
    public ImageView imageView;

    public ViewHolder(View itemView) {
        super(itemView);
        userIdView = (TextView)itemView.findViewById(R.id.userId);
        jobTitleNameView = (TextView)itemView.findViewById(R.id.jobTitleName);
        employeeCodeView = (TextView)itemView.findViewById(R.id.employeeCode);
    }
}

@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(
            parent.getContext());
    View v = inflater.inflate(R.layout.activity_listview, parent, false);
    viewHolder = new ViewHolder(v);
    return viewHolder;
}

@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
    final HashMap<String, Object> userDetails = myDataSet.get(position);
    String userId = (String) userDetails.get("userId");
    String jobTitleName = (String) userDetails.get("jobTitleName");
    String employeeCode = String.valueOf(userDetails.get("employeeCode"));
    image = (String) userDetails.get("image");

    ImageDownloader imageDownloader = new ImageDownloader();
    imageDownloader.execute(viewHolder);


    holder.userIdView.setText(userId);
    holder.jobTitleNameView.setText(jobTitleName);
    holder.employeeCodeView.setText(employeeCode);
}

@Override
public int getItemCount() {
    return myDataSet.size();
}

This is the class written inside this class for downloading image.

private class ImageDownloader extends AsyncTask<ViewHolder,ViewHolder,ViewHolder>{

    @Override
    protected ViewHolder doInBackground(ViewHolder... params) {
        viewHolder = params[0];

        URL url = null;
        try {
            url = new URL(image);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream inputStream = connection.getInputStream();
            bitmap = BitmapFactory.decodeStream(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return viewHolder;
    }

    @Override
    protected void onPostExecute(ViewHolder result){
        viewHolder.imageView.setImageBitmap(bitmap);
    }
   }
 }

Can someone help me with this....

Please find the log below

    03-24 16:27:48.421 19806-20764/com.example.rini.listviewandroid W/System.err: java.net.ConnectException: failed to connect to www.scri8e.com/208.87.227.250 (port 80): connect failed: ETIMEDOUT (Connection timed out)
    03-24 16:27:48.421 19806-20764/com.example.rini.listviewandroid W/System.err:     at libcore.io.IoBridge.connect(IoBridge.java:124)
    03-24 16:27:48.421 19806-20764/com.example.rini.listviewandroid W/System.err:     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:183)
    03-24 16:27:48.421 19806-20764/com.example.rini.listviewandroid W/System.err:     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:456)
    03-24 16:27:48.421 19806-20764/com.example.rini.listviewandroid W/System.err:     at java.net.Socket.connect(Socket.java:882)
    03-24 16:27:48.421 19806-20764/com.example.rini.listviewandroid W/System.err:     at com.android.okhttp.internal.Platform.connectSocket(Platform.java:174)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at com.android.okhttp.Connection.connect(Connection.java:152)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:276)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:382)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:106)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at com.example.rini.listviewandroid.MyAdapter$ImageDownloader.doInBackground(MyAdapter.java:94)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at com.example.rini.listviewandroid.MyAdapter$ImageDownloader.doInBackground(MyAdapter.java:77)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:292)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at java.lang.Thread.run(Thread.java:818)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err: Caused by: android.system.ErrnoException: connect failed: ETIMEDOUT (Connection timed out)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at libcore.io.Posix.connect(Native Method)
    03-24 16:27:48.422 19806-20764/com.example.rini.listviewandroid W/System.err:     at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:111)
    03-24 16:27:48.423 19806-20764/com.example.rini.listviewandroid W/System.err:     at libcore.io.IoBridge.connectErrno(IoBridge.java:137)
    03-24 16:27:48.423 19806-20764/com.example.rini.listviewandroid W/System.err:     at libcore.io.IoBridge.connect(IoBridge.java:122)
    03-24 16:27:48.423 19806-20764/com.example.rini.listviewandroid W/System.err:   ... 17 more

Upvotes: 1

Views: 1306

Answers (4)

Abhinav Pawar
Abhinav Pawar

Reputation: 431

Here is a Picasso library .xactly meant for what you are looking for .I have been using this since long,highly custom-able.You can even choose to either cache the images for faster loading from network or from storage.An as simple as that

Picasso.with(context).load("https://i.sstatic.net/jEIKP.jpg").into(imageView);

Upvotes: 0

Andy Joyce
Andy Joyce

Reputation: 2832

While it's not a direct solution could I recommend using a Library like Picasso and Glide? It will significantly reduce the number of lines of code. Here are some links to the libraries

Picasso: http://square.github.io/picasso/

Glide: https://futurestud.io/blog/glide-getting-started

Your onBindViewHolder would then look something like this

@Override 
public void onBindViewHolder(ViewHolder holder, final int position) {
    final HashMap<String, Object> userDetails = myDataSet.get(position);
    String userId = (String) userDetails.get("userId");
    String jobTitleName = (String) userDetails.get("jobTitleName");
    String employeeCode =     String.valueOf(userDetails.get("employeeCode"));
    image = (String) userDetails.get("image");

    //With Picasso 
    Picasso.with(context).load(image).into(viewHolder.imageView);

    //With Glide 
    Glide.with(context).load(image).into(viewHolder.imageView);

    holder.userIdView.setText(userId);
    holder.jobTitleNameView.setText(jobTitleName);
    holder.employeeCodeView.setText(employeeCode);
} 

Upvotes: 2

SHICONG CAO
SHICONG CAO

Reputation: 219

There might cause problem to decode bitmap like this:

 bitmap = BitmapFactory.decodeStream(inputStream);

if some bytes are wrong, the result will return null.

You can try like below:

private static Bitmap urlFetch(Context context, String url) {
    try {
        URL u = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) u.openConnection();
        int rspCode = conn.getResponseCode();
        if (rspCode != 200) {
            return null;
        }
        InputStream inputStream = null;
        inputStream = conn.getInputStream();
        long total = conn.getContentLength();
        try {
            return BitmapFactory.decodeStream(new FlushedInputStream(
                        inputStream));
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } 
    return null;
}


static class FlushedInputStream extends FilterInputStream {
    public FlushedInputStream(InputStream inputStream) {
        super(inputStream);
    }

    @Override
    public long skip(long n) throws IOException {
        long totalBytesSkipped = 0L;
        while (totalBytesSkipped < n) {
            long bytesSkipped = in.skip(n - totalBytesSkipped);
            if (bytesSkipped == 0L) {
                int b = read();
                if (b < 0) {
                    break; // we reached EOF
                } else {
                    bytesSkipped = 1; // we read one byte
                }
            }
            totalBytesSkipped += bytesSkipped;
        }
        return totalBytesSkipped;
    }
}

Basically it will skip wrong byte to prevent all the bitmap went wrong.

By the way, Imageloader is a complex method, you need to consider memory consuming(handling bitmap is really easy to cause OOM), cache and reuse the bitmap as file or lrucache, downlaoding multiple pictures at the same time without degrading the UX(thread pool), so I recommend you to use a third-party library to handle this job. Universe-image-loader is a good choice.

Upvotes: 0

Berdimurat Masaliev
Berdimurat Masaliev

Reputation: 345

Try modify ImageDownloader like this. I am not sure, but it should work;

private class ImageDownloader extends AsyncTask<Void,Void,Bitmap> {
    private ViewHolder viewHolder;
    private String image;

    public ImageDownloader(ViewHolder viewHolder, String image) {
        this.viewHolder = viewHolder;
        this.image = image;
    }

    @Override
    protected Bitmap doInBackground(Void... params) {

        URL url = null;
        try {
            url = new URL(image);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream inputStream = connection.getInputStream();
            return BitmapFactory.decodeStream(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Bitmap bitmap){
        if(bitmap != null) {
            viewHolder.imageView.setImageBitmap(bitmap);
        }
    }
}

Than in adapter:

ImageDownloader imageDownloader = new ImageDownloader(viewHolder, image);
imageDownloader.execute();

Upvotes: 0

Related Questions