web-dev-qa-db-ja.com

ハンドラーメッセージにオブジェクトを配置する

別のスレッドでインターネットから画像をダウンロードする必要があります。
次に、ハンドラーメッセージでその画像オブジェクトをUIスレッドに送信します。

私はすでにこれを持っています:

...
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...

誰か助けてもらえますか?

ちなみに、これは最も効率的な方法です
オブジェクトをUIスレッドに渡すには?

皆さん、ありがとうございました!

20
Tsimmi

この種の操作にはAsyncTaskを使用します。進行状況の更新やダウンロードが完了したら、UIスレッドにフックすることができます。次の例は、その方法を示しています。

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

それが役に立てば幸い

4
m6tt

パーティーに遅れるのはわかっていますが、単一のプロセス内でサービスを使用する方が簡単な方法があります。次の行を使用して、任意のObjectMessageに接続できます。

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

これは、現在のプロジェクトでうまく機能しています。
ああ、私はAsyncTaskオブジェクトの使用をやめようとしています。これは、それらがコードの結合を過度に増加させると考えているためです。

69
Caspar Harmer

まず、正確にどこで例外が発生しますか?インスタンスをバンドルに入れるとき、またはそれを取得するときに?

混同していると思います。あなたのバンドルを作成するとき、あなたは書きます

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

チェックする別のいくつかのポイント:

  • クラスMyObjectParcelableを実装していますか? (そうだと思いますが、そうでなければコンパイルできません)
  • 変数objectには、Parcelableを実装するインスタンスが含まれていますか?
7
exhuma

オブジェクトを1つだけ転送する場合は、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;  
}

楽しい :)

3
tryp