Поместить объект в сообщение обработчика - PullRequest
20 голосов
/ 09 июня 2010

Мне нужно загрузить изображение из Интернета, в другом потоке,
, а затем отправить этот объект изображения в сообщении обработчика в поток пользовательского интерфейса.

У меня уже есть:

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

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

handler.sendMessage(msg);

И когда я получаю это сообщение, я хочу извлечь объект:

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

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

Но это дает мне:

...java.lang.ClassCastException...

Кто-нибудь может помочь?

И, кстати, это самый эффективный способ
для передачи объекта в поток пользовательского интерфейса?

Спасибо всем!

Ответы [ 4 ]

68 голосов
/ 29 июня 2011

Я знаю, что опаздываю на вечеринку, но есть более простой способ, если вы используете службу в рамках одного процесса. Вы можете присоединить любой произвольный Object к вашему Message, используя эту строку:

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

Это хорошо работает для меня в моих текущих проектах.
О, и я ухожу от использования AsyncTask объектов, поскольку считаю, что они слишком сильно увеличивают связывание кода.

7 голосов
/ 09 июня 2010

Первое: где именно вы берете исключение? При помещении экземпляра в связку или при его извлечении?

Я верю, что ты все перепутал. При создании вашего пакета вы пишете

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

Итак, вы назначаете экземпляр "objet" клавише "MyObject". Но при получении вашего экземпляра вы пишете:

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

Здесь вы извлекаете экземпляр из ключа "IpTile". Обратите внимание, что "IpTile" != "MyObject". Попробуйте использовать следующее для извлечения объекта:

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

или наоборот, попробуйте заменить код, который помещает экземпляр в пакет, следующим образом:

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

Еще несколько пунктов для проверки:

  • Реализует ли класс MyObject Parcelable? (Полагаю, иначе вы не смогли бы скомпилировать)
  • Содержит ли переменная object экземпляр, который реализует Parcelable?
4 голосов
/ 09 июня 2010

Я бы использовал AsyncTask для такого рода операций. Это позволяет вам подключиться к вашей теме пользовательского интерфейса для таких вещей, как обновления прогресса и после завершения загрузки. В приведенном ниже примере показано, как это сделать:

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);
  }
}

Надеюсь, что поможет

3 голосов
/ 03 августа 2017

Если вы пересылаете только один объект, вы можете сделать это с помощью класса Message, вам не нужно создавать пакет - это проще и быстрее.

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

mHandler.sendMessage(message); 

Получить его классически

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

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

Наслаждайтесь:)

...