0

I am trying to load images from a url and I have used Picasso, however I'd like to know how to do it without an external library if possible. I know I have to get an Asynctask going but I'm not sure how to implement it.

This is my getview code

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View row = convertView;
    if(position==0){

        NewsObj currNews = news.get(position);
        DataHandler dh;
        if(convertView==null){
            LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.firstnews,parent,false);
            dh = new DataHandler();
            dh.newsTitle = (TextView)row.findViewById(R.id.newsTitle);
            dh.newsDate = (TextView)row.findViewById(R.id.newsDate);
            dh.newsIcon = (ImageView)row.findViewById(R.id.newsIcon);
            row.setTag(dh);
        }else{
            dh = (DataHandler)row.getTag();
        }
        NewsObj no = (NewsObj)this.getItem(position);
        new AsyncDownloadTask().execute(row,no.getImgurl());
        dh.newsTitle.setText(no.getTitle());
        dh.newsDate.setText(no.getDate());

    }else{

        NewsObj currNews = news.get(position);
        DataHandler dh;
        if(convertView==null){
            LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.newslist,parent,false);
            dh = new DataHandler();
            dh.newsTitle = (TextView)row.findViewById(R.id.newsTitle);
            dh.newsDate = (TextView)row.findViewById(R.id.newsDate);
            dh.newsIcon = (ImageView)row.findViewById(R.id.newsIcon);
            row.setTag(dh);
        }else{
            dh = (DataHandler)row.getTag();
        }
        NewsObj no = (NewsObj)this.getItem(position);
        new AsyncDownloadTask().execute(row,no.getImgurl());

        dh.newsTitle.setText(no.getTitle());
        dh.newsDate.setText(no.getDate());

    }
    return row;
}


 private class AsyncDownloadTask extends AsyncTask<Object, String, Bitmap>{

    private View view;
    private Bitmap bitmap = null;
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if(bitmap!=null&&view!=null){
            ImageView newsIcon = (ImageView)view.getTag(R.id.newsIcon);
            newsIcon.setImageBitmap(bitmap);
        }
    }

    @Override
    protected Bitmap doInBackground(Object... params) {
        view = (View)params[0];
        String uri = (String)params[1];
        try{
            InputStream inputStream = new URL(uri).openStream();
            bitmap = BitmapFactory.decodeStream(inputStream);
        }catch (Exception e){
            e.printStackTrace();
        }
        return bitmap;
    }
}

This is my async task

UPDATE : Encountering null pointer exceptions

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageBitmap(android.graphics.Bitmap)' on a null object reference
JianYA
  • 2,750
  • 8
  • 60
  • 136

3 Answers3

3

You can write your own code. But using a library handles all the boilerplate code which is associated with a library. Unless otherwise, I also recommend that you use a library. Here are some of the boilerplate things that you need to consider when writing your own code.

  1. Memory management: External libraries take care of making sure the images doesn't take up all of the memory available for your app. Android Bitmaps are very memory conscious to deal with and therefore better to give this part to a library.

  2. Handling activity destruction: If you rotate your phone while an image download is in progress, it will recreate the activity and then you will need to handle cancellation of the previous requests and start them again.

  3. Cancelling previous requests: Image libraries are written such that list view items which are no longer visible do not continue downloading. Suppose you scroll down. Then there is no point in downloading the images which are part of the first rows. You should cancel such downloads and start downloading the new images. Image downloader libraries are written to take care of these.

  4. Caching: The image libraries use both a memory cache and a disk cache to store the downloaded bitmaps. Therefore, they only download new images unless they are not available.

  5. Loading large bitmaps off the UI Thread: Suppose your app includes large Bitmaps. In order to load them into your view, you must first load them from disk. You need to write code so that loading them do not block the main UI thread.

  6. Loading relevant image sizes: Your application may run either a new Android device with high screen density or an old device with low screen density. Depending on your target device, you won't need to load a full resolution image if your device does not support such screen density. Usually libraries handle this for you,

These are just a few of the boilerplate stuff to consider. Therefore, I highly recommend that you use a good library for the image loading part unless it's so so required!!!

Ruchira Randana
  • 4,021
  • 1
  • 27
  • 24
  • I used Picasso to handle the url image stuff. It was just one line. Unfortunately the client did not want additional libraries. – JianYA May 29 '16 at 06:21
  • Why don't you try to convince the client by stating what I said in my answer. You can find more explanations if you search a bit more! – Ruchira Randana May 29 '16 at 06:22
0

Simply you can use java.net.URL for loading an image into ImageView like

    ImageView loadedImage;

    @override
    protected Bitmap doInBackground(String... url) {
        String URL_OF_IMAGE = url[0];
        Bitmap bitmap = null;
        try {
            InputStream in = new java.net.URL(URL_OF_IMAGE).openStream();
            bitmap= BitmapFactory.decodeStream(in);
        } catch (Exception e) {
        }
        return bitmap;
    }

    protected void onPostExecute(Bitmap result) {
        loadedImage.setImageBitmap(result);
    }

But notice that you should have extend AsyncTask that should have first parameter as String and last as Bitmap like

private class DowmloadImage extends AsyncTask<String, Void, Bitmap>
Shree Krishna
  • 8,474
  • 6
  • 40
  • 68
  • Hello, thank you but where do I call this in my getview? – JianYA May 29 '16 at 05:43
  • @JianYA Yah execute the AsyncTask in `getView();` by passing the url of image. – Shree Krishna May 29 '16 at 05:44
  • Can you add that to your answer? I'm still confused as I'm not sure how to pass the url. – JianYA May 29 '16 at 05:45
  • @JianYA you can refer [this](http://stackoverflow.com/questions/2471935/how-to-load-an-imageview-by-url-in-android) question's answer's for more reference. – Shree Krishna May 29 '16 at 05:45
  • I tried entering this in my getView but i get an error where I can't find my imageview new AsyncDownloadTask((ImageView)findViewById(R.id.newsIcon)).execute(no.getImgurl()); – JianYA May 29 '16 at 05:49
  • Your Asynctask class should be outside of any methods, And have you referenced the link I mentioned above ? – Shree Krishna May 29 '16 at 05:52
  • Yeah I saw. They don't take into account that I have a getView – JianYA May 29 '16 at 05:56
  • my AsyncTask is a class outside. Ill update my question – JianYA May 29 '16 at 05:56
  • see [this](http://stackoverflow.com/questions/11778140/using-asynctask-to-load-images-into-a-custom-adapter) question and accepted answer both. How they passed a view and url as well and executed the Asynctask to load the image. Do same as they did. And Load image as I suggested in my answer. Refer the above link clearly if you got trouble in loading images. – Shree Krishna May 29 '16 at 05:59
  • Thanks, I've updated my question. I seem to get a ImageView.setImageBitmap(android.graphics.Bitmap)' on a null object reference – JianYA May 29 '16 at 06:10
  • post the full crash log if you've not fixed that. – Shree Krishna May 29 '16 at 06:17
  • added it to question. Thank you – JianYA May 29 '16 at 06:18
  • 1
    You have to set the tag before using getTag method, Like OP (question asker) has set that in his newView method. See the [question](http://stackoverflow.com/q/11778140/5067493) – Shree Krishna May 29 '16 at 06:23
  • 1
    This does answer the question directly. However in practice, there is a lot of issues which arise when you try to handle image loading on your own. I've given a list below. Please have a look at them! – Ruchira Randana May 29 '16 at 06:24
  • Thank you so much. I understand that this is not good practice. I'll let them know. – JianYA May 29 '16 at 06:27
  • @RuchiraRandana And you think your answer which is suggesting OP to force the client to convince using picasso is pointing to the question correctly ? I know all the benefit of using external library and disadvantages of not using that. See clearly what OP is searching for, He clearly wrote we shouldn't use external libraries, You are forcing him to use that in your answer. And you mean my answer is not pointing to the question ? – Shree Krishna May 29 '16 at 06:31
  • @JianYA Yah try to convince them, If they agree then you do not have to do a lots of work to handle the exceptions and certain cases. – Shree Krishna May 29 '16 at 06:32
  • @RuchiraRandana I'm sorry that I thought you've wrote *This doesn't answer the question*, So that I was a bit upset, Do not take it negatively I realized you wrote positively. – Shree Krishna May 29 '16 at 06:34
  • Dear @ShreeKrishna. Please don't get excited in a situation like this. For a SO person with over 4000 reputation that is not worthy. This is an open forum and people should have an environment where they can discuss and constructively criticise to get to an optimum solution. I see you have responded as I'm typing a response. Than you. However, it should be noted that it's better to guide people like JianYA when they face such situations and help them with the actual problem. I hope you take my comment constructively and not destructively. Thank you. – Ruchira Randana May 29 '16 at 06:38
  • @RuchiraRandana Yah I know that Rep. is nothing then the help. And I apologize that I thought you've wrote 'This doesn't answer the question', And I take your suggestion positively. Your elaborations is very useful though. – Shree Krishna May 29 '16 at 06:42
  • @ShreeKrishna: I appreciate your positive attitude towards criticism now! That's how it should be!!! Cheers!!! – Ruchira Randana May 29 '16 at 06:47
0

You can Use Network Image View instead of Imageview. It surely makes your life easier.

<com.android.volley.toolbox.NetworkImageView
    android:id="@+id/networkImageView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:background="#000000"/>

This should be replaced in place of Image view in the required XML File.

public ImageLoader getImageLoader() {
    getRequestQueue();
    if (mImageLoader == null) {
        mImageLoader = new ImageLoader(this.mRequestQueue,
                new LruBitmapCache());
    }
    return this.mImageLoader;
}

The class above also creates an ImageCache which works with normal volley cache, but only caching images for requests.

To Set the Image URL.

advImage.setImageUrl("Your Image URL", AppController.getInstance().getImageLoader());

Call the Image Loader Function accordingly. You can also set the defalult placeholder image as well.

Jatin Jha
  • 880
  • 9
  • 17