Question

I need to download an image from the internet, in a different thread,
and then send that image object in the handler message, to the UI thread.

I already have this:

...
Message msg = Message.obtain();

Bundle b = new Bundle();
b.putParcelable("MyObject", (Parcelable) object);
msg.setData(b);

handler.sendMessage(msg);

And when I receive this message, I want to extract the object:

...
public void handleMessage(Message msg) {
    super.handleMessage(msg);

    MyObject objectRcvd = (MyObject) msg.getData().getParcelable("IpTile");
    addToCache(ipTile);
    mapView.invalidate();
}

But this is giving me:

...java.lang.ClassCastException...

Can anyone help?

And by the way, is this the most efficient way
to pass an object to the UI Thread?

Thank you all!

Was it helpful?

Solution

I would use an AsyncTask for this kind of operation. It allows you to hook into your ui thread for things like progress updates and once you have finished your download. The example below shows how one should be done:

class GetImageTask extends AsyncTask<String, int[], Bitmap> {

  @Override
  protected Bitmap doInBackground(String... params) {
    Bitmap bitmap = null;

    // Anything done here is in a seperate thread to the UI thread 
    // Do you download from here

    // If you want to update the progress you can call
    publishProgress(int progress); // This passes to the onProgressUpdate method

    return bitmap; // This passes the bitmap to the onPostExecute method
  }

  @Override
  protected void onProgressUpdate(Integer... progress) {
    // This is on your UI thread, useful if you have a progressbar in your view
  }

  @Override
  protected void onPostExecute(Bitmap bitmapResult) {
    super.onPostExecute(bitmapResult);
    // This is back on your UI thread - Add your image to your view
    myImageView.setImageBitmap(bitmapResult);
  }
}

Hope that helps

OTHER TIPS

I know I'm late to the party, but there is an easier way if you are using the service within a single process. You can attach any arbitrary Object to your Message using this line:

msg.obj = new CustomObject() // or whatever object you like

This is working well for me in my current projects.
Oh, and I'm moving away from using AsyncTask objects, as I believe they increase code coupling too much.

First: Where exactly do you get the exception? When putting the instance into the bundle, or upon retrieving it?

I believe your mixing things up. When creating your bundle, you write

b.putParcelable("MyObject", (Parcelable) object);

So you are assigning the instance "objet " to the key "MyObject". But when retrieving your instance you write:

MyObject objectRcvd = (MyObject) msg.getData().getParcelable("IpTile");

Here, you are retrieving an instance from the key "IpTile". Note that "IpTile" != "MyObject". Try using the following to retrieve the object:

MyObject objectRcvd = (MyObject) msg.getData().getParcelable("MyObject");

or the other way around, try replacing your code which puts the instance into the bundle with this:

b.putParcelable("IpTile", (Parcelable) object);

Another few points to check:

  • Does the class MyObject implement Parcelable? (I suppose so, otherwise you wouldn't be able to compile)
  • Does the variable object contain an instance which implements Parcelable?

If you are forwarding only one object, you can do it using the Message class, you don't need to create a bundle - it's easier and faster.

Object myObject = new Object();
Message message = new Message();
message.obj = myObject;
message.what = 0;

mHandler.sendMessage(message); 

Retrieve it classicaly

@Override
public void handleMessage(Message msg) {
    super.handleMessage(msg);

    // ...
    Object object = (Object) msg.obj;  
}

Enjoy :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top