0

更新1

さらにデバッグを行ったところ、コンストラクターはメインUIスレッドから実行されていますが、handleMessage(Message)メソッドは作成したスレッドで実行されているため、ハンドラーの理解とは完全に矛盾しています。

問題

私はしばらくの間Androidに取り組んできましたが、文書化されていないように見える問題に遭遇しました。私は自分のコードで特別なことは何もしていません。ハンドラーのhandleMessageメソッドからアラートダイアログやトーストメッセージなどのUI要素をアプリケーションで作成できないようです。

さらに、「スレッドがLooper.prepare()を呼び出さなかった」という例外が発生します。ただし、Threadオブジェクト内にハンドラーを作成していないため、Looper.prepare()を呼び出す必要はないと思います。メインUIスレッドでコンストラクターを呼び出し、それを新しいスレッドのコンストラクターに渡します。

私が期待すること

トーストメッセージとアラートダイアログが表示されます。

実際に何が起こるか

何もない。アプリケーションでデバッガーを実行しましたが、JVMがスレッドを起動することがわかりました。runメソッドが呼び出され、メッセージがディスパッチされます。ハンドラーがメソッドを処理し、AlertDialogとToastメッセージを作成するすべてのメソッドを実行しましたが、何も表示されません。

このアプリケーションは、4.2を実行しているエミュレーター、4.0.4を実行している友人のSamsung Galaxy S3、および2.3.5を実行している自分のDroidX2で実行しました。

プログラムの流れ

  1. UIスレッドでハンドラーを作成します。
  2. メッセージをハンドラーにディスパッチするスレッドを作成して開始します。
  3. ハンドラーがメッセージを処理します

ソースコード

http://pastebin.com/cRfaW7b0

package com.nguyenmp.ErrorTest;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MyActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Init the UI
        setContentView(R.layout.main);

        //Create a new handler, passing it the current activity context
        final Handler handler = new MyHandler(MyActivity.this);

        //Bind a listener to the button on the UI
        View view = findViewById(R.id.button);
        view.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                //Start a new thread that will send a message to that handler
                new MyThread(handler).start();
            }

        });
    }

    private class MyThread extends Thread {
        private final Handler mHandler;

        MyThread(Handler handler) {
            mHandler = handler;
        }

        @Override
        public void run() {
            //Dispatch message to UI thread asynchronously
            Looper.prepare();
            mHandler.dispatchMessage(mHandler.obtainMessage());
        }
    }

    private class MyHandler extends Handler {
        private final Context mContext;

        MyHandler(Context context) {
            mContext = context;
        }

        @Override
        public void handleMessage(Message msg) {
            //Show that we got the message
            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            builder.setTitle("HelloWorld");
            builder.setMessage("It worked!");
            builder.show();

            //Another variant of showing that we got the message
            Toast.makeText(mContext, "Message Received", Toast.LENGTH_SHORT).show();

            System.out.println("Yeah");
        }
    }
}
4

2 に答える 2

1

http://developer.android.com/reference/android/os/Handler.html#sendMessage(android.os.Message)を使用 して、後でhandleMessageによって処理されるメッセージを送信する必要があります。

于 2013-02-19T06:40:49.563 に答える
0

問題は、現在のスレッドですぐに実行される dispatchMessage(Message) を呼び出していたことです。最初に Handler を作成した元のスレッドのメッセージキューに指定された Message をエンキューする sendMessage(Message) を使用する必要がありました。

于 2013-02-19T06:01:24.763 に答える