Question

I'm having a problem with this app that should be simple fix but I just can't figure out what the hell I'm doing wrong...All the app does is download an image in one thread and set the image in the other thread. I changed the ReadFile class to return a Drawable object into the variable finalImage then I have onPostExecute to set that image to the ImageView but...the only thing it is showing is an Android icon. Any suggestions would be appreciated. I'm guessing it has to do with the way I'm returning the Drawable from ReadFile class but I can't figure out what exactly.

package com.example.imageviewer;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.widget.ImageView;

public class MainActivity extends Activity {

    private final String URL_STRING = "http://cdn.theatlantic.com/static/infocus/putin091311/s_p15_0RTXUL0R.jpg";
    private final String FILENAME = "s_p15_0RTXUL0R.jpg";
    private ImageView fileImageView; 
    public Drawable finalImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fileImageView = (ImageView) findViewById(R.id.fileImageView);

        new DownloadFile().execute();
        new ReadFile().execute();

    }

    class DownloadFile extends AsyncTask<Void, Void, String> {
        @Override
        protected String doInBackground(Void... params) {
            // download and write the file
            try{
                // get the URL object
                URL url = new URL(URL_STRING);

                // get the input stream
                InputStream in = url.openStream();

                // get the output stream
                FileOutputStream out = 
                        openFileOutput(FILENAME, Context.MODE_PRIVATE);

                // read input and write output
                byte[] buffer = new byte[1024];
                int bytesRead = in.read(buffer);
                while (bytesRead != -1)
                {
                    out.write(buffer, 0, bytesRead);
                    bytesRead = in.read(buffer);
                }
                out.close();
                in.close();

                // return a message
                return "File downloaded";
            }
            catch (IOException e) {
                return "Error: " + e.toString();
            }
        }

        @Override
        protected void onPostExecute(String message) {
            Log.d("Test", message);

            fileImageView.setImageDrawable(finalImage);

        }                
    }

        public class ReadFile extends AsyncTask <Void, Void, Drawable>{

            @Override
            protected Drawable doInBackground(Void...params){
                try {
                    FileInputStream in = openFileInput(FILENAME);
                    Drawable image = Drawable.createFromStream(in, FILENAME);
                    fileImageView.setImageDrawable(image);
                    Log.d("Test", "File read");            
                } 
                catch (Exception e) {
                    Log.e("Test", "Error: " + e.toString());
                }
                return finalImage;
            }

        }

}
Was it helpful?

Solution

Your problem is here:

new DownloadFile().execute();
new ReadFile().execute();

As these are Asynchronous Tasks, they're running at the same time, and ReadFile is attempting to open your image file before DownloadFile has finished.

You merely need to move the new ReadFile().execute(); to the onPostExecute() method of DownloadFile.

Then also add the following to ReadFile, to get the ImageView to refresh:

@Override
    protected void onPostExecute(Drawable nada) {
        fileImageView.invalidate();
    }

I tested to make sure that's all that was needed, and got a picture of Putin with a dog.

OTHER TIPS

You should return "image" instead of "finalImage" from the ReadFile task.

Also, you can try this instead of onPostExecute:

public class MainActivity extends Activity implements AsyncResponse {
    ...

    void processFinish(Drawable output) {
        fileImageView.setImageDrawable(finalImage);
    }
}

AsyncResponse.java:

public interface AsyncResponse {
    void processFinish(Drawable output);
}

ReadFile.java:

        public class ReadFile extends AsyncTask <Void, Void, Drawable>{

            @Override
            protected Drawable doInBackground(Void...params){
                Drawable image;
                try {
                    FileInputStream in = openFileInput(FILENAME);
                    image = Drawable.createFromStream(in, FILENAME);
                    Log.d("Test", "File read");            
                } 
                catch (Exception e) {
                    Log.e("Test", "Error: " + e.toString());
                }
                return image;
            }



    @Override
    protected void onPostExecute(Drawable result) {
        delegate.processFinish(result);
    } 
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top