线程间通讯----Handler

   Android中规定:
java

   (1)不能阻碍UI主线程,达到5秒以上会自动报错(ANR应用程序没法响应)
android

   (2)不要让UI主线程以外的线程去更新主UI,不然绘世界报错
ide

   例:post

public class MainActivity extends Activity {
    private TextView tv;
                                                                                                      
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.textView1);
        findViewById(R.id.strat).setOnClickListener(new OnClickListener() {
                                                                                                              
            @Override
            public void onClick(View arg0) {
                thread.start();//单击按钮启动一个子线程
            }
        });
    }
                                                                                                     
    Thread thread = new Thread(){
        public void run() {
            tv.setText("hello");//在子线程中更新UI
        };
    };
                                                                                                     
                                                                                                      
}

   结果:
this

   那么如何解决上面出现的问题呢?能够用咱们的Handler
spa

   一:Handler
线程

   Handler对象的使用和线程相关,也就是说,他会绑定一个线程,让这个耗时的操做在新建的线程上完成,而达到不阻碍主UI线程的操做,从而达到线程之间的通讯。
对象

   二:用途
blog

   (1)发送消息
资源

   可使用post(runnable对象)、postDelay(runnable对象,int时间间隔)等方法发送Runnable对象,从而与主UI线程进行通讯。

   可使用sendMessage(Message对象)、sendMessage(Message对象,int时间间隔)等方法发送Message对象,从而与主UI线程进行通讯。

   (2)接收消息

   可使用handleMessage(Message对象)方法处理接收获得的Message

   三:经常使用的Handler方法

   (1)post(runnable对象):启动线程,在线程中处理耗时操做

   (2)postDelay(runnable对象,int时间间隔): 每隔多长时间执行一次线程

   (3)sendMessage(Message对象):发送消息给主线程

   (4)handleMessage(Message对象):接收消息,并更新UI

   四:发送Runnable对象,从而与主UI线程进行通讯

功能:在新建的线程中,完成计数操做,并更新主UI上的控件。

   (1)建立Handler对象,并实例化

// 建立Handler对象
    private Handler handler = new Handler();

   (2)建立线程,完成计数操做,并更新主UI

// 建立线程
    Runnable runnable = new Runnable() {
        int count = 0;
        @Override
        public void run() {
            count++;
            tv.setText(count + "");// 更新UI
            // System.out.println("我是子线程");
            handler.postDelayed(runnable, 1000);// 每隔一秒执行一次线程
        }
    };

   (3)主界面添加按钮。启动按钮: 经过handler启动子线程;中止按钮:移除线程对象

private Button startBtn, stopBtn;// 声明按钮
    private TextView tv;// 声明文本框
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 查找资源
        startBtn = (Button) findViewById(R.id.start);
        stopBtn = (Button) findViewById(R.id.stop);
        tv = (TextView) findViewById(R.id.textView1);
        // 为按钮添加监听
        startBtn.setOnClickListener(this);
        stopBtn.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.start:
            handler.post(runnable);// 经过Handler启动线程
            break;
        case R.id.stop:
            // 移除子线程
            handler.removeCallbacks(runnable);
            break;
        }
    }

   ◆结果:单击start按钮,主UI开始更新,单击stop时候中止更新。

   五:使用sendMessage(Message对象)和handleMessage(Message对象)实现Message对象的接受与发送

    功能:这里利用的sendMessage发送消息,用handleMessage方法去更新UI。让ProgressBar自动更新,在TextView中实时显示进度条中的值。

具体实现:

   (1)建立handler对象和子线程,用Message封装消息,经过handler的sendMessage方法发送消息。

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            count += 10;
//          Message message = new Message();// 建立消息的承载对象这样会建立不少个Message对象
            //建立Message对象承载信息
            Message message = handler.obtainMessage();//这样建立的Message只会有一个
            //Message存储消息
            message.arg1 = count;// 承载数据
            handler.sendMessage(message);// 发送消息
            handler.postDelayed(runnable, 1000);// 每隔一秒执行一次线程
        }
    };

(2)实例化handler对象,实现其中的handleMessage方法,接收消息,更新UI

private Handler handler = new Handler() {
        public void handleMessage(Message msg) {// 接受消息
            pgbar.setProgress(msg.arg1);// 更新主界面的UI
            tv.setText(msg.arg1+"");
            if (msg.arg1 ==100) {// 作判断
                count=0;
                tv.setText("到头了。。");
                handler.removeCallbacks(runnable);// 移除UI
            }
        };
    };

   (3)在主界面中给按钮添加监听,经过Handler对象以启动和移除线程

private ProgressBar pgbar;
    private TextView tv;
    private int count = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pgbar = (ProgressBar) findViewById(R.id.progressBar1);
        tv = (TextView) findViewById(R.id.textView1);
                                                                                                                                                                                                                           
        findViewById(R.id.start).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                handler.post(runnable);// 启动线程
            }
        });
        findViewById(R.id.stop).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                handler.removeCallbacks(runnable);// 移除线程
            }
        });
    }

结果:单击开始按钮,滚动条与TextView同时更新,且同步,任意位置单击按钮时,都可以中止。

   六:运用Handler实现屏幕的自动滚屏

   (1)在主界面上添加一个ScrollView,在其中的的LinearLayout下添加一个TextView,里面添加足够多的文字

   (2)在主界面上实例化Handler对象,在其中的handleMessage方法中实现滚屏效果,具体以下

handler = new Handler() {//实例化Handler对象
            public void handleMessage(android.os.Message msg) {
                if (msg.what == 1) {//判断消息的标示
                    int startPosition = sv.getScrollY();//获得当前的Y值
                    if (startPosition == 0 || startPosition != lastPosition) {//判断条件,看看是否是到达底部或者是否是开始位置
                        lastPosition = sv.getScrollY();//如果,则得到Y值
                        sv.scrollBy(0, 2);//X坐标不变,Y值每次加2 实现竖屏滚动
                        handler.sendEmptyMessageDelayed(1, 100);//发送消息
                    }
                }
            };
        };
        handler.sendEmptyMessageDelayed(1, 100);//发送消息标识为1 的消息,每一个0.1秒发送一个消息

   (3)结果:出现自动滚屏效果,可自行查看。

   还有一种比Handler轻量级的线程通讯处理方式-----AsynTask,我们明日再续。

相关文章
相关标签/搜索