꿈소년의 개발 이야기

[Android] Handler Thread looper 본문

Android Development

[Android] Handler Thread looper

꿈소년 2011. 3. 8. 15:51
반응형
Android 에서는 thread 간에 통신을 하기 위해서 handler 와 looper 를 제공하고 있다.

child thread 에서 어떤 작업 결과를 main thread 에 알려주는 방법은 handler 를 이용해서 message 를 보내는 것이다.

main thread 는 message queue 와 연결되어 있기 때문이다.

child thread 에서도 main thread 와 같이 handler 를 이용해 message 를 받고자 한다면, looper 를 써야 한다.

looper 가 없으면 이런 실행 에러가 난다.
("Can't create handler inside thread.....)

실행 중인 child thread 로 뭔가 message 를 보내고 싶으면 child thread 에 handler 와 looper 를 이용해서 구현해야 한다..

아래 원문이 이런 내용인 것 같다...

원문 참조...



Android provides Handler and Looper for threads to communication with each other

For example, a child thread is launched to create an image from the web. After it is done, it notifies the main thread (or the UI thread) by sending a message using the handler that’s bound to the main thread’s message queue. 

The data produced by the child thread can also be included in the message. I often use this pattern if I want the main thread to update the UI with the data produced by the child thread (you probably already know why if you have been playing with threads in Android).

When a Handler is created, it’s bound to the message queue of the thread that created it. 

If you create it in the main thread, you don’t need any extra code to loop the message queue for the main thread since it’s already been started when you run your application. However, if you are creating a Handler in a child thread, you need to initialize the thread to listen to its message queue before creating the Handler.


Whenever the Handler receives a message, it would run the handleMessage(…). You can do some expensive operations in there. For example, you need to constantly send some data to the server. It probably would be more efficient if you have a thread listening for the messages to do the job instead of creating and running a new thread each time you need to do so.

If you are done with the looper, don’t forget to stop it by using its quit() method. For example:

mChildHandler.getLooper().quit();

Here is an example of creating a two-way communication between the main thread and a child thread:

example)


public class ThreadMessaging extends Activity {


    private static final String TAG = "ThreadMessaging";

    private TextView mTextView;

    private Handler mMainHandler, mChildHandler;

    private Handler mh;


    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        mTextView = (TextView)findViewById(R.id.text);


        /*

         * Start the child thread.

         */

        new ChildThread().start();


        /*

         * Create the main handler on the main thread so it is bound to the main

         * thread's message queue.

         */

        mMainHandler = new Handler() {


            public void handleMessage(Message msg) {


                Log.i(TAG, "Got an incoming message from the child thread - "  + (String)msg.obj);


                /*

                 * Handle the message coming from the child thread.

                 */

                mTextView.setText(mTextView.getText() + (String)msg.obj + "\n");

            }

        };


        Log.i(TAG, "Main handler is bound to - " + mMainHandler.getLooper().getThread().getName());


        Button button = (Button)findViewById(R.id.button);

        button.setOnClickListener(new OnClickListener() {


            public void onClick(View v) {


                /*

                 * Send a message to the child thread.

                 */

                Message msg = mChildHandler.obtainMessage();

                msg.obj = mMainHandler.getLooper().getThread().getName() + " says Hello";

                mChildHandler.sendMessage(msg);

                Log.i(TAG, "Send a message to the child thread - " + (String)msg.obj);

            }

        });

    }


    @Override

    protected void onDestroy() {


        Log.i(TAG, "Stop looping the child thread's message queue");


        /*

         * Remember to stop the looper

         */

        mChildHandler.getLooper().quit();


        super.onDestroy();

    }


    class ChildThread extends Thread {


        private static final String INNER_TAG = "ChildThread";


        public void run() {


            this.setName("child");


            /*

             * You have to prepare the looper before creating the handler.

             */

            Looper.prepare();


            /*

             * Create the child handler on the child thread so it is bound to the

             * child thread's message queue.

             */

            mChildHandler = new Handler() {


                public void handleMessage(Message msg) {


                    Log.i(INNER_TAG, "Got an incoming message from the main thread - " + (String)msg.obj);


                    /*

                     * Do some expensive operation there. For example, you need

                     * to constantly send some data to the server.

                     */

                    try {


                        /*

                         * Mocking an expensive operation. It takes 100 ms to

                         * complete.

                         */

                        sleep(100);


                        /*

                         * Send the processing result back to the main thread.

                         */

                        Message toMain = mMainHandler.obtainMessage();

                        toMain.obj = "This is " + this.getLooper().getThread().getName() +

                            ".  Did you send me \"" + (String)msg.obj + "\"?";

                        mMainHandler.sendMessage(toMain);

                        Log.i(INNER_TAG, "Send a message to the main thread - " + (String)toMain.obj);


                    } catch (InterruptedException e) {

                        // TODO Auto-generated catch block

                        e.printStackTrace();

                    }


                }

            };


            Log.i(INNER_TAG, "Child handler is bound to - " + mChildHandler.getLooper().getThread().getName());


            /*

             * Start looping the message queue of this thread.

             */

            Looper.loop();

        }

    }

}


[출처] http://skyswim42.egloos.com/3546223