GK Soft
GK Soft

Reputation: 103

Change View from other thread

I wrote a code to download an image from internet. And i have to show it in a ImageView which is dynamically created.

And i am getting an error that Only the original thread that created a view hierarchy can touch its views. I know i have to write a handle but how can i do that?

Here is my code:

public class ResimCek implements Runnable {

        int resimID = 0;

        public ResimCek(int parcaID) {
            // store parameter for later user
            resimID = parcaID;
        }

        public void run() {

            int resID = getResources().getIdentifier(Integer.toString(resimID) , "tag", getPackageName()); 
            ImageView resim = (ImageView) findViewById(resID);

            Drawable image = ImageOperations(getBaseContext(),"http://141.11.11.206/parca/" + Integer.toString(resimID) + ".jpg" ,"I" + Integer.toString(resimID) + ".jpg");

            // I AM GETTING ERROR HERE ******************
            resim.setImageDrawable(image); // *************************
        }
    }

    private Drawable ImageOperations(Context ctx, String url, String saveFilename) {
        try {
            InputStream is = (InputStream) this.fetch(url);
            Drawable d = Drawable.createFromStream(new URL(url).openConnection().getInputStream(),saveFilename);
            return d;
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public Object fetch(String address) throws MalformedURLException,IOException {
        URL url = new URL(address);
        Object content = url.getContent();
        return content;
    }
    private void MalzemeEkle(String malzemeKodu, String malzemeTanimi) {
        ImageView parcaresmi = new ImageView(this);
        parcaresmi.setId(Integer.parseInt(malzemeKodu));
        Runnable r = new ResimCek(Integer.parseInt(malzemeKodu)); 
        new Thread(r).start(); 
}

Upvotes: 2

Views: 6270

Answers (3)

user1506104
user1506104

Reputation: 7086

You can create a handler AND make very sure that the handler is assigned the correct looper. If it is the UI thread that created your view hierarchy:

Handler handler = new Handler(context.getMainLooper());

If it is another thread that created your view hierarchy, you need to have a access to that looper and assign it to your handler like so:

Handler handler = new Handler(threadLooper);

Note that if you do something like this:

Handler handler = new Handler();

Default constructor associates this handler with the Looper for the current thread. If this thread does not have a looper, this handler won't be able to receive messages so an exception is thrown.

This is very important to understand. Else, you might get an exception:

CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

Then later on, execute your code that needs to run on that specific thread:

handler.post(new Runnable() {
    @Override
    public void run() {
        ...
    }
});

Cheers!

Upvotes: 0

Dany Y
Dany Y

Reputation: 7031

You should create a handler :

    final Handler   myHandler   = new Handler() {
                                    @Override
                                    public void handleMessage(Message msg)
                                    {
                                        /*do all your ui action here to display the image ()*/
                                        resim.setImageDrawable(image);
                                    }
                                };

And in your runnable when the image is downloaded call :

myHandler.sendEmptyMessage(0);

There are other options for handler you can find here http://developer.android.com/reference/android/os/Handler.html

Upvotes: 1

ngesh
ngesh

Reputation: 13501

public class ResimCek implements Runnable {

        int resimID = 0;

        public ResimCek(int parcaID) {
            // store parameter for later user
            resimID = parcaID;
        }

        public void run() {

            int resID = getResources().getIdentifier(Integer.toString(resimID) , "tag", getPackageName()); 
            ImageView resim = (ImageView) findViewById(resID);

            Drawable image = ImageOperations(getBaseContext(),"http://141.11.11.206/parca/" + Integer.toString(resimID) + ".jpg" ,"I" + Integer.toString(resimID) + ".jpg");

            // I AM GETTING ERROR HERE ******************
            resim.setImageDrawable(image); // *************************
        }
    }



new Handler().post(new ResimCek(Integer.parseInt(malzemeKodu))); instead of new Thread(r).start(); 

by any case if this is an Activity.. then

runOnUIThread(new ResimCek(Integer.parseInt(malzemeKodu))); `instead of new Thread(r).start();` 

will also work..

Upvotes: 2

Related Questions