Android中规定:

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

(2)不要让UI主线程之外的线程去更新主UI,否则绘世界报错

例:

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        };    };                                                                                                                                                                                                           }

结果:

那么如何解决上面出现的问题呢?可以用我们的Handler

一:Handler

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

二:用途

(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,咱们明日再续。



更多相关文章

  1. Android(安卓)代理拦截系统层代码
  2. Android开发之《Android应用开发揭秘》UI事件汇总
  3. Android延迟执行PostDelayed
  4. Android(安卓)LayoutInflater
  5. Android:一个很简单的扑克游戏(从项目资源创建图像)
  6. Android中双击返回键退出应用实例代码
  7. Android互联网访问图片并在客户端显示的方法
  8. 【Android】对话框AlertDialog的使用(一)
  9. RxJava学习笔记(Schedulers)

随机推荐

  1. mysql通过Navicat分区实操讲解
  2. Mysql忘记密码的几种解决方案
  3. mysql varchar类型求和实例操作
  4. 实例操作MySQL短链接
  5. 浅析MySQL数据的导出与导入知识点
  6. 为什么MySQL数据库索引选择使用B+树?
  7. Mysql的水平分表与垂直分表的讲解
  8. CMD命令操作MySql数据库的方法详解
  9. MySQL查询重复数据(删除重复数据保留id最
  10. Mysql5.6修改root密码教程