按钮学习配合handler(Button):

2020-07-01  本文已影响0人  Epimenides

情景说明:

在网络上获取数据,并将获取到的数据在本地进行显示。

既然要在网络上获取数据,必然要用到多线程编程。下面对该情形进行模拟:

  1. 创建一个Button控件名字为btn
  2. 设置Button控件的长宽都和内容(content)一样长
  3. Button绑定一个"btnOnClick"事件
  4. Button按钮上显示Handler
<Button
        android:id = "@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="btnOnClick"
        android:text="@string/handler"/>

错误示范:在MainActivity.java中实现btnOnClick事件,并模拟网络请求在支线程中改变按钮显示文字

public class MainActivity extends AppCompatActivity {
    private Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        btn = (Button) findViewById(R.id.btn);
    } 
    //实现 btnOnClick事件
    public void btnOnClick(View view) {
       //匿名内部类实现线程通信
        new Thread(new Runnable(){
            @Override
            public void run(){  
                //模拟网络请求延时2秒
                try{
                    Thread.sleep(2*1000);
                } catch (InterruptedException e){
                    e.printStackTrace();
                }
                //在支线程中改变UI控件(按钮)显示的文字
                btn.setText("1234567");
            }
        }).start(); 
    }
}

异步线程(支线程)中改变主线程的UI控件会抛出如下异常:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

如此引发了一个问题?------UI主线程和异步支线程如何进行通信?

使用Handler:

​ Handler在android中负责发送和处理消息,通过它可以实现其他线程与主线程之间的消息通信。

使用Looper:

​ Looper负责管理线程的消息队列和消息循环

使用Message:

​ Message是线程之间通讯的消息载体,充当集装箱的功能,里面可以存放任何你想要传递的内容。

​ 当其他线程与主线程产生通信的时候,这时候就可以将想要表达的信息封装到Message里面。将Message传递给主线程。拿到Message就可以拿到里面存放的想要表达的东西了。

使用MessageQueue:

​ MessageQueue是消息队列(遵循先进先出的原则),作用是保存待处理线程的消息。

public class MainActivity extends AppCompatActivity {
    private Button btn;
    //申明一个用于发送和接收消息的一个类handler
    private Handler handler = new Handler(){
        //后面为了处理这个消息要重载hanleMessage方法:接收消息等待处理的地方
        @Override
        public void handleMessage(Message msg){
            //已经回到主线程里面
            switch(msg.what){
                    case1:
                    //如果Message对象得到的信息是1,就改变控件的文字
                        btn.setText("1234567");
                        break;
                    case2:
                        break;
                    case3:
                        break;
            }
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        btn = (Button) findViewById(R.id.btn);
    } 
    //实现 btnOnClick事件
    public void btnOnClick(View view) {
       //匿名内部类实现线程通信
        new Thread(new Runnable(){
            @Override
            public void run(){
                //模拟网络请求延时2秒
                try{
                    Thread.sleep(2*1000);
                } catch (InterruptedException e){
                    e.printStackTrace();
                }
                //用handler发送消息通知主线程,更新UI界面
                handler.sendEmptyMessage(1);
            }
        }).start(); 
    }
}
上一篇下一篇

猜你喜欢

热点阅读