runOnUiThread简单应用
首先runOnUiThread是Activity内部的方法,在运用的时候最好指明当前环境变(Context).
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(RunOnUIThreadActivity.this, "UI操作...", 1000).show();
}
});
}
}).start();
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
new Thread(new Runnable() {
@Override
public void run() {
if(isClose)
return;
if(i!=0)
Toast.makeText(RunOnUIThreadActivity.this, i+"", 1000).show();
i++;
handler.postDelayed(this, 2000);
}
}).start();
}
上面两个其实原理一样,runOnUiThread这个会调用父类中的
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
首先判断是否是UI线程,不是的话就post,如果是的话就正常运行该线程.
只要经过主线程中的Handler.post或者postDelayed处理线程runnable则都可以将其转为UI主线程.再说Handler的机制就是来处理线程与UI通讯的.
activity的runOnUiThread步骤使用
我们都知道在android系统中我们是不能在UI线程外更新界面的,如果你要想在一个UI线程外更新UI的话,你得用那Handler啊,或是异步线程类等一些方式,下面就会大家讲解一个很简单,却很实用的方法让UI在一个“用户线程”中更新,直接用acitivty类的runOnUiThread(runnable run)方法,
本实例通过一个界面每五秒换一个文字来实现那道理,
不多说直接上代码,
main.xml布局文件:
<RelativeLayout xmlns:android=";
xmlns:tools=";
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:padding="@dimen/padding_medium"
tools:context=".TimerThreadExample"
android:textSize="40pt" />
</RelativeLayout>
二:主activity类代码:
public class ThreadExample extends Activity {
protected int splashTime = 3000;
TextView tv1;
String[] name = {"A","N","D","R","O","I","D"};
int timer =0;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv1 = (TextView) findViewById(R.id.textView1);
Thread th=new Thread(){
@Override
public void run(){
try
{
for (timer = 0; timer < 7; timer++)
{
int waited = 0;
while(waited < splashTime)
{
Thread.sleep(100);
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
tv1.setText(name[timer]);
}
catch(Exception e)
{
e.printStackTrace();
}
}
});
waited += 100;
}
}
}catch (InterruptedException e) {
}
}
};
th.start();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Runnable 并不一定是新开一个线程,比如下面的调用方法就是运行在UI主线程中的:
Handler mHandler=new Handler(); mHandler.post(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub } });
官方对这个方法的解释如下,注意其中的:“The runnable will be run on the user interface thread. ”
boolean android.view.View .post(Runnable action)
Causes the Runnable to be added to the message queue. The runnable will be run on the user interface thread.
Parameters:
action The Runnable that will be executed.
Returns:
Returns true if the Runnable was successfully placed in to the message queue. Returns false on failure, usually because the looper processing the message queue is exiting.
我们可以通过调用handler的post方法,把Runnable对象(一般是Runnable的子类)传过去;handler会在looper中调用这个Runnable的Run方法执行。
Runnable是一个接口,不是一个线程,一般线程会实现Runnable。所以如果我们使用匿名内部类是运行在UI主线程的,如果我们使用实现这个Runnable接口的线程类,则是运行在对应线程的。
具体来说,这个函数的工作原理如下:
View.post(Runnable)方法。在post(Runnable action)方法里,View获得当前线程(即UI线程)的Handler,然后将action对象post到Handler里。在Handler里,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。在Handler再次处理该Message时,有一条分支(未解释的那条)就是为它所设,直接调用runnable的run方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI。
如下图,前面看到的代码,我们这里Message的callback为一个Runnable的匿名内部类
这种情况下,由于不是在新的线程中使用,所以千万别做复杂的计算逻辑。