zoukankan      html  css  js  c++  java
  • Handler使用

    Handler是android中一个用来处理发送和接受的消息,主要有两个功能:

        1)按计划发送消息或执行某个Runnanble(使用POST方法);

        2)处理消息队列中从其他线程发送来的消息,避免线程冲突(常见于更新UI线程)

      使用Handler之前,首先你要清楚两个问题:

      第一:当一个android应用程序启动时,系统会开启一个主线程,也就是UI线程,这个主线程负责管理界面中的控件,响应用户的操作。

      第二:没有使用另外一个线程启动Handler的时候,Handler是运行在主线程中的,它通过Message对象和子线程进行通信。

      既然Handler默认是运行在主线程中的,说明我们同样不能使用handler处理耗时的操作,否则会出现ANR(Application Not Response)现象。

      那么什么时候会用到Handler呢

      举个例子: 比如我们需要下载一个文件时,这个耗时的操作要放到一个子线程中执行。当文件下载完成后,怎么通知主线程下载完毕呢。

      这个时候,我们可以让子线程发送一个消息给Handler,Handler在收到下载完成的消息时,就可以通知主线程更新UI,通知用户下载完成了。

    下面给出一个Handler的小例子,它主要演示

      功能1:   按计划发送消息或执行某个Runnanble(使用POST方法);

    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
     
    /**
     * @author abing
     * 
     */
    public class HandlerTest extends Activity {
        /** Called when the activity is first created. */
        Handler handler = new Handler();
        Runnable updateThread = new Runnable() {
     
            @Override
            public void run() {
                System.out.println("UpdateThread():Thread Id="
                        + Thread.currentThread().getId() + " , Thread Name= "
                        + Thread.currentThread().getName());
                // 延迟3000ms,将需要被执行的线程加入到线程队列中去
                handler.postDelayed(updateThread, 3000);
     
            }
     
        };
     
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
     
            // 初始化控件
            TextView myTextView = (TextView) findViewById(R.id.myTextView);
     
            Button startButton = (Button) findViewById(R.id.startButton);
            Button endButton = (Button) findViewById(R.id.endButton);
            startButton.setText("start");
            endButton.setText("end");
     
            // 设置监听器
            startButton.setOnClickListener(new StartButtonListener());
            endButton.setOnClickListener(new EndButtonListener());
     
        }
     
        class StartButtonListener implements OnClickListener {
            @Override
            public void onClick(View v) {
                System.out.println("start click():Thread Id="
                        + Thread.currentThread().getId() + " , Thread Name= "
                        + Thread.currentThread().getName());
                handler.post(updateThread);
            }
        }
     
        class EndButtonListener implements OnClickListener {
     
            @Override
            public void onClick(View v) {
                System.out.println("end click():Thread Id="
                        + Thread.currentThread().getId() + " , Thread Name= "
                        + Thread.currentThread().getName());
     
                handler.removeCallbacks(updateThread);
            }
     
        }
     
    }

      可以看到,在没有特殊声明的情况下,Handler和Main线程是在同一个线程中,下面给出另一个实例,这个实例演示:

      功能2:处理消息队列中从其他线程发送来的消息,避免线程冲突(常见于更新UI线程)

       在这个实例中,我们将处理消息队列的Handler放到一个单独的线程中

    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.HandlerThread;
    import android.os.Looper;
    import android.os.Message;
     
    /**
     * @author abing
     * 
     */
    public class HandlerTest02 extends Activity {
        /** Called when the activity is first created. */
        Handler handler = new Handler();
     
        @Override
        public void onCreate(Bundle savedInstanceState) {
            try {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
     
                // 打印当前线程的ID
                System.out.println("Activity Thread :"
                        + Thread.currentThread().getId());
     
                // 开启一个带有looper的线程类,该类实现了使用looper来处理消息队列的功能,这个类由android提供
                HandlerThread handlerThread = new HandlerThread("handler_thread");
                handlerThread.start();
     
                MyHandler myHandler = new MyHandler(handlerThread.getLooper());
                Message msg = myHandler.obtainMessage();
     
                // 使用bundle对象来传递数据
                Bundle b = new Bundle();
                b.putInt("age", 20);
                b.putString("name", "张三");
     
                msg.setData(b);
     
                // 讲msg发送给目标对象,目标对象就是生成该msg的handler对象
                msg.sendToTarget();
     
            } catch (Exception e) {
                e.printStackTrace();
                System.out.print(e.getMessage());
            }
     
        }
     
        /**
         * MyHandler类
         * 
         * @author abing
         * 
         */
        class MyHandler extends Handler {
            public MyHandler() {
            }
     
            /**
             * 此函数的意思是将Handler与looper所在的线程绑定 handler会调用looper所在的线程处理消息
             * 
             * @param looper
             */
            public MyHandler(Looper looper) {
                super(looper);
            }
     
            @Override
            public void handleMessage(Message msg) {
                Bundle b = msg.getData();
                System.out.println("age is : " + b.getInt("age"));
                System.out.println("name is " + b.getString("name"));
                System.out.println("Handler Thread;"
                        + Thread.currentThread().getId());
            }
        }
     
    }

    运行结果:

     

      可以看到,发送消息的线程为1,处理消息的线程的id为9。这样处理消息队列的线程和主线程就分开了。

    转载地址:http://www.67tgb.com/?p=451

  • 相关阅读:
    与MS Project相关的两个项目
    最后的报告bug
    oo第二阶段的总结
    第一阶段的反思和改变
    面向对象设计与构造第四次课程总结
    面向对象设计与构造第三次课程总结
    面向对象设计与构造第一次课程总结
    OO游记之六月篇
    OO游记之五月篇
    OO游记之四月篇
  • 原文地址:https://www.cnblogs.com/garygou/p/2852956.html
Copyright © 2011-2022 走看看