user2955143
user2955143

Reputation: 177

Saving and showing images from server in activity

I'm working on fetching data from server and display it. I'm using volley library to show the information. I managed to show everything. But now I want to show images by saving it first and then display from sd card. So I created a thread to download the images. But it is affecting the loading time of the activity. Please help me how to solve that problem. My code goes like this.

public View getView(int i, View view, ViewGroup viewGroup) {
            ViewHolder vh ;
           if(view == null){
               vh = new ViewHolder();
               view = lf.inflate(R.layout.row_listview,null);

               vh.tvSen = (TextView)view.findViewById(R.id.textSend);
               vh.tvRece = (TextView)view.findViewById(R.id.textRec);
               vh.tvMsB = (TextView)view.findViewById(R.id.textMBody);

               vh.nwImg = (NetworkImageView)view.findViewById(R.id.twitterUserImage);

               view.setTag(vh);
          }
            else{
               vh = (ViewHolder) view.getTag();
           }
            DataModel nm = arrData.get(i);

            vh.tvSen.setText(nm.getSender());

            vh.tvMsB.setText(nm.getMessageBody());
            vh.tvMsB.setTextColor(Color.WHITE);

            ImageSave saveit = new ImageSave(IMAGES[i]);
            FutureTask<String> future = new FutureTask<String>(saveit);
            ExecutorService executor = Executors.newFixedThreadPool(1);
            executor.execute(future);
            future.isDone();
           vh.nwImg.setImageUrl(IMAGES[i], imageLoader);

            return view;
        }

Upvotes: 0

Views: 86

Answers (1)

fede1024
fede1024

Reputation: 3098

I did something similar in a project i'm working on.

This is part of the code of the activity:

protected void onCreate(Bundle savedInstanceState) {    

    ...

    // image = image identifier, i.e. "pic1", "pic2"...

    ImageView img = (ImageView) this.findViewById(R.id.big_icon);
    String path = ImageManager.getCachedImage(image, this);

    if(path != null)
        setImage(path, img);
    else {
        Callback c = new ImageCallBack(img);
        new ImageManager(c, this).execute(image);
    }

    ...
}


// Image loading callback
private class ImageCallBack implements Callback {
    ImageView img;

    public ImageCallBack(ImageView img){
        this.img = img;
    }   
    @Override
    public boolean handleMessage(Message msg) {
        String path = (String) msg.obj;
        setImage(path, this.img);
        return false;
    }
}

The ImageManager class extends AsyncTask and is used to asynchronously dowload the image and store it on the SD card. When download is done, the provided callback is called. In this way, you callback can show the image (and possibly hide a spinner, just to show to the user that something is loading). It also has a static member to check if the image is already in cache (returns null otherwise). Some of the code, easy to extend:

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.http.util.ByteArrayBuffer;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler.Callback;
import android.os.Message;

public class ImageManager extends AsyncTask<String, Void, String> {
    private Callback callback;
    private Context context;
    private String imagesUrl;

    public ImageManager(Callback cb, Context con){
        callback = cb;
        context = con;
        imagesUrl = "http://picturesurl.com/something/";
    }

    @Override
    protected String doInBackground(String... imageCode) {
        InputStream is = null;
        String outFile = null;

        try {
            URL url = new URL(imagesUrl + imageCode[0] + ".png");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(30000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("GET");
            conn.setDoInput(true);

            // Starts the query
            conn.connect();
            is = conn.getInputStream();

            BufferedInputStream bufferinstream = new BufferedInputStream(is);

            ByteArrayBuffer baf = new ByteArrayBuffer(5000);
            int current = 0;
            while((current = bufferinstream.read()) != -1){
                baf.append((byte) current);
            }

            outFile = context.getExternalFilesDir(null) + "/" + imageCode[0] + ".png";

            FileOutputStream fos = new FileOutputStream(outFile);
            fos.write(baf.toByteArray());
            fos.flush();
            fos.close();
        } catch(IOException e){
            System.out.println("ImageManager error!" + imageCode[0]);
            e.printStackTrace();
            return null;
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch(IOException e){
                    System.out.println("ImageManager error on close!");
                    e.printStackTrace();
                    return null;
                }
            }
        }
        return outFile;
    }

    public static String getCachedImage(String image, Context context){
        String path = context.getExternalFilesDir(null) + "/" + image + ".png";
        File f = new File(path);
        if (f.exists())
            return path;
        else
            return null;
    }

    // onPostExecute displays the results of the AsyncTask.
    @Override
    protected void onPostExecute(String result) {
        Message m = new Message();
        m.obj = result;
        if(result != null)
            System.out.println("New image cached: " + result);
        else
            System.out.println("Error downloading image.");
        this.callback.handleMessage(m);
    }

}

Upvotes: 1

Related Questions