android:
id="@+id/myTextView"
android:
textSize="15pt"
android:
layout_toRightOf="@id/myButton"
android:
layout_alignTop="@id/myButton"
android:
textColor="#FF0000"
android:
layout_width="wrap_content"
android:
layout_height="wrap_content"/>
Activity01类
Java代码收藏代码
packagexiaohang.zhimeng;
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.widget.Button;
importandroid.widget.TextView;
publicclassActivity01extendsActivity{
privateButtonmyButton;
privateTextViewmyTextView;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myButton=(Button)findViewById(R.id.myButton);
myTextView=(TextView)findViewById(R.id.myTextView);
myButton.setOnClickListener(newMyButtonListener());
}
classMyButtonListenerimplementsOnClickListener{
@Override
publicvoidonClick(Viewv){
newThread(){
@Override
publicvoidrun(){
//我们在这里更新了UI设置了TextView的值
myTextView.setText("张三");
}
}.start();
}
}
}
接下来我们以看图片的方式看看这是怎样的一个异常。
请大家点击图片查看大图
android.view.ViewRoot$CalledFromWrongThreadException:
Onlytheoriginalthreadthatcreatedaviewhierarchycantouchitsviews.就是这样一个异常这个异常告诉我们不可以再子线程中更新UI元素比如我们上边那个例子设置了一个TextView的值。
所有与UI相关的操作都不可以在子线程中执行都必须在UI线程中执行。
这个异常大家以后可能会经常遇到多加注意就是了。
我们继续,下面我们说说线程交互方面的东西。
就比如我们想做点这些事情上边不是说了不能在子线程中更新UI那比如我想在子线程中定义一个字符串然后通过发消息的方式Message把这个字符串发送给主线程也就是UI线程让UI线程来设置这个TextView的值为我们刚刚在子线程中定义的字符串。
或者我想在子线程中开启音乐服务,或者把它停止该怎么做呢?
要知道怎么做先让我们了解一下这几个对象吧!
它们分别是
MessageQueueHandlerLooper下面对它们进行详细说明
MessageQueue
在单线程模型下,为了解决类似的问题,Android设计了一个MessageQueue(消息队列),线程间可以通过该MessageQueue并结合Handler和Looper组件进行信息交换。
lMessageQueue
MessageQueue是一个消息队列,用来存放通过Handler发布的消息。
消息队列通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列。
如果没有消息队列对象则会抛出空指针异常。
Android在第一次启动程序时会默认会为UIthread创建一个关联的消息队列,用来管理程序的一些上层组件,activities,broadcastreceivers等等。
你可以在自己的子线程中创建Handler与UIthread通讯。
也就是说我们程序一启动我们的UI线程也就是主线程就会有一个消息队列,而如果我们自己另外开启的一个子线程就不会有MessageQueue(消息队列)对象。
这一点大家务必知道。
lHandler
通过Handler你可以发布或者处理一个消息或者是一个Runnable的实例。
每个Handler都会与唯一的一个线程以及该线程的消息队列关联。
当你创建一个新的Handler时候,默认情况下,它将关联到创建它的这个线程和该线程的消息队列。
也就是说,如果你通过Handler发布消息的话,消息将只会发送到与它关联的这个消息队列,当然也只能处理该消息队列中的消息。
这里大家就得理解一下了也就是说我们一个Handler对应一个线程以及附属于该线程的消息队列。
就比如我们现在有一个Handler对象这个Handler在UI线程中创建叫xh_Handler那么我们根据上边的说明应该可以告诉我这个xh_Handler是和那个线程关联的?
如果我用这个Handler发消息的话它将发给那个线程的消息队列?
如果你知道了我想一般情况下你肯定是知道的。
说明你很懂。
我们继续。
这时我们用这个Handler对象发送消息
Handler对象也可以发送消息哦,它有发送消息的方法。
下面就说到了待会大家看示例程序也会发现主要就是看它怎么使用。
Handler的主要的方法有:
1)publicfinalbooleansendMessage(Messagemsg)
把消息放入该Handler所关联的消息队列,放置在消息队列尾部。
这里请允许我多说一句就是我们把消息放进去的一端消息不会阻塞但是处理消息的一端就有可能会阻塞。
欢迎收看看图频道。
2)publicvoidhandleMessage(Messagemsg)
关联该消息队列的线程将通过调用Handler的handleMessage方法来接收和处理消息,通常需要子类化Handler来实现handleMessage。
lLooper
Looper扮演着一个Handler和消息队列之间通讯桥梁的角色。
程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。
Looper也把消息队列里的消息广播给所有的Handler,Handler接受到消息后调用handleMessage进行处理。
1)可以通过Looper类的静态方法Looper.myLooper得到当前线程的Looper实例,如果当前线程未关联一个Looper实例,该方法将返回空(null)它不会抛空指针异常。
2)可以通过静态方法Looper.getMainLooper方法得到主线程的Looper实例这里需要注意一下主线程默认是有一个Looper对象的。
但是我们自己定义的子线程没有的。
那么我们怎么在子线程中得到Looper对象呢?
如果一个线程中调用Looper.prepare(),那么系统就会自动的为该线程建立一个消息队列,然后调用Looper.loop();之后就进入了消息循环,这个之后就可以发消息、取消息、和处理消息。
这个如何发送消息和如何处理消息可以再其他的线程中通过Handle来做,但前提是我们的Hanle知道这个子线程的Looper,但是你如果不是在子线程运行Looper.myLooper(),一般是得不到子线程的looper的。
好了示例演示时间到了。
示例名称:
线程交互
这个例子主要向大家说明线程之间是如何进行交互的。
请大家静下心来好好看看。
如果你也是android新手的话。
先说一下我们具体要实现什么功能,一共有三个按钮第一个按钮用来设置一个TextView上显示的值。
当我们第一次点击它的时候它就会把值显示在TextView当我们在一点一下就会把这个值清空。
什么也不显示了。
这个按钮的的背景图片我做了点处理。
就是默认情况下这个按钮一张图片,按下按钮又会换成另外一张图片,松开按钮又会换一张图片。
这是怎么做到的说完这个例子会给大家解释。
至于线程之间是怎么传递消息的大家就看代码吧。
另外2个按钮时用来开启和关闭音乐服务的,注意当我们点击开始按钮的时候就会开始播放音乐并且把歌曲的名称显示在一个TextView上。
当我们点击关闭按钮的时候就会停止音乐的播放,好了废话不多说了大家看代码吧。
O对了差点忘记了我们应该先收看看图频道之运行效果。
好了下边我们来看布局文件一共有2个布局文件一个是用来定义我们的布局我这里用的是相对布局RelativeLayout下边是main.xml
Xml代码收藏代码
xmlversion="1.0"encoding="utf-8"?
>
android:
orientation="vertical"
android:
layout_width="fill_parent"
android:
background="@drawable/bg0"
android:
layout_height="fill_parent">
android:
id="@+id/textview01"
android:
textColor="#FF0000"
android:
layout_width="fill_parent"
android:
layout_height="wrap_content"
android:
text="@string/hello"
/>