情景说明:
在网络上获取数据,并将获取到的数据在本地进行显示。
既然要在网络上获取数据,必然要用到多线程编程。下面对该情形进行模拟:
- 创建一个Button控件名字为
btn
- 设置
Button
控件的长宽都和内容(content
)一样长 - 给
Button
绑定一个"btnOnClick
"事件 - 在
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();
}
}
网友评论