1

以下のテスト アプリは、Cristian Baita によるこのスレッド チュートリアルに大まかに基づいています。myThread の run() メソッドから送信されたメッセージが MainActivity のハンドラーによって受信されないことを除いて、期待どおりに機能します。

スレッドのコンストラクターで MainActivity のハンドラーを myThread に渡しています。次に、そのハンドラーの sendMessage() メソッドを使用してメッセージを MainActivity に送り返しますが、ハンドラーはそれを受信して​​いないようです。どうしてこれなの?

注: 私は、Eclipse でのデバッグにブレークポイントを使用するのがスレッドの苦痛であることを発見したので、アプリの実行を追跡する代わりに、Log ステートメントを使用してトップに行きました。

この投稿の最後に完全なコードを掲載しましたが、要約すると次のようになります。

MyThread クラスのコンストラクターは、以下に示すように、呼び出し元のアクティビティからハンドラーを取得します。

public class MyThread extends Thread {

    // Reference to mainHandler from the mainThread
    private Handler parentHandler;

    // Constructor
    public MyThread(Handler pHandler) {
        parentHandler = pHandler;
    }

MainActivity の onCreate() メソッドでスレッドを作成するときに、handler を渡しますmainHandler

myThread = new MyThread(mainHandler);
myThread.start();

次に、MyThread の run() メソッドに次のように記述します。

    Message messageToParent = Message.obtain();
    messageToParent.what = 2;
    Log.i("myThread", "About to send message to parent ...");
    parentHandler.sendMessage(messageToParent);

メッセージはmainHandler、MainActivity で定義されたものによって受信されます。

    public Handler mainHandler = new Handler() {
        public void handleMessages(Message msg){
            Log.i("MainActivity", "Message Received");
            switch(msg.what) {
                case 2:
                    Log.i("MainActivity", "Handled message. msg.what = " + msg.what);
    ....

これが実行されているときに LogCat ウィンドウを見ると、MainActivity が "Message Received" または "Handled message..." をログに記録しないことがわかります。そのため、メッセージは宛先に届きません。

メインアクティビティ:

public class MainActivity extends Activity {

private MyThread myThread;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    myThread = new MyThread(mainHandler);
    myThread.start();

    // Message the thread
    Message msgToThread = Message.obtain();
    msgToThread.what = 4;
    Log.i("MainActivity", "About to send message to thread...");
    myThread.getHandler().sendMessage(msgToThread);
}

public Handler mainHandler = new Handler() {
    public void handleMessages(Message msg){
        Log.i("MainActivity", "Message Received");
        switch(msg.what) {
            case 2:
                Log.i("MainActivity", "Handled message. msg.what = " + msg.what);

                // Message the thread
                Message msgToThread = Message.obtain();
                msgToThread.what = 6;
                myThread.getHandler().sendMessage(msgToThread);

                break;
            default:
                Log.i("MainActivity", "Unhandled message. msg.what = " + msg.what);
                break;
        }
    }
};
}

MyThread クラス:

public class MyThread extends Thread {

// Reference to mainHandler from the mainThread
private Handler parentHandler;

// Constructor
public MyThread(Handler pHandler) {
    parentHandler = pHandler;
}

// Local handler for messages to this thread
private Handler myThreadHandler = new Handler() {
    public void handleMessage(Message msg) {

        switch(msg.what) {

            case 4:
                Log.i("myThread", "Handled message. msg.what = " + msg.what);
                break;

            case 6:
                Log.i("myThread", "Handled message. msg.what = " + msg.what);
                break;

            default:
                Log.i("myThread", "Unhandled message. msg.what = " + msg.what);
                break;              
        }
    }
};


@Override
public void run() {     
    super.run();

    int count = 0;
    boolean keepGoing = true;

    try {

        while(true) {

            Log.i("myThread", "run() method - while loop is ticking ..." + count);

            // some arbitrary conditions to make stuff happen
            switch(count) {
                case 5:
                    Message messageToParent = Message.obtain();
                    messageToParent.what = 2;
                    Log.i("myThread", "About to send message to parent ...");
                    parentHandler.sendMessage(messageToParent);
                    break;
                case 10:
                    keepGoing = false;
                    break;
            }

            if(!keepGoing) {
                Log.i("myThread", "myThread is going to stop");
                break;
            }

            count++;
            sleep(500);

        }

    } 
    catch (Exception e) {
        Log.e("My Log", "Thread Loop Exception - " + e);
    }
    Log.i("myThread", "myThread has reached the end of it's run() method");
}

public Handler getHandler() {
    return myThreadHandler;
}

}
4

2 に答える 2

0

handleMessage()ハンドラーのメソッドを作成するときに、何をしているのか誤解していることに気付きました。

ハンドラー用の新しいメソッドを作成していると思ったので、少し違う名前を付けましたhandleMessages()(複数形に注意してください)。

実際、ハンドラーの既存のメソッドの 1 つをオーバーライドしています。

私がフォローしていたサンプル コードでは、Cristian Baita はメソッドの@Override前にステートメントを使用していません。あなたとあなたのコンパイラがバグを強調するのに便利handleMessage()なので、これは十分に公平です。恥ずかしいことに、何も上書きしていなかったので、そこになかった@Overrideと仮定したのは私のせいです。@Override願わくば、この間違いが学習曲線の他の一部の人に役立つことを願っています.

ところで、Cristian Baita の 3 つのスレッド チュートリアルは非常に明確に説明されており、従うのが簡単なので、引き続き徹底的にお勧めします。問題は私の仮定でした!

于 2013-09-07T07:42:41.327 に答える