runonuithread 和用runnable还是thread的区别

利用Activity.runOnUiThread(Runnable)把更新ui的代码创建在Runnable中,然后在需要更新ui时,把这个Runnable对象传给Activity.runOnUiThread(Runnable).
Runnable对像就能在ui程序中被调用。
* Runs the specified action on the UI thread. If the current thread is the UI
* thread, then the action is executed immediately. If the current thread is
* not the UI thread, the action is posted to the event queue of the UI thread.
* @param action the action to run on the UI thread
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
action.run();
从上面的源代码中可以看出,程序首先会判断当前线程是否是UI线程,如果是就直接运行,如果不是则post,这时其实质还是使用的Handler机制来处理线程与UI通讯。
private ProgressDialog progressD
&Context&mContext;
progressDialog = new ProgressDialog(mContext);
String stri = mContext.getResources().getString(R.string.Is_sending_a_request);
progressDialog.setMessage(stri);
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
new Thread(new Runnable() {
public void run() {
((Activity)mContext).runOnUiThread(new Runnable() {
public void run() {
progressDialog.dismiss();
String s1 = mContext.getResources().getString(R.string.send_successful);
Toast.makeText(mContext, s1, Toast.LENGTH_LONG).show();
} catch (final Exception e) {
((Activity)mContext).runOnUiThread(new Runnable() {
public void run() {
progressDialog.dismiss();
String s2 = mContext.getResources().getString(R.string.Request_add_buddy_failure);
Toast.makeText(mContext, s2 + e.getMessage(), Toast.LENGTH_LONG).show();
}).start();
用这种方式创建ProgressDialog就比较方便,或者刷新adapter也比使用Thread+Handler方便。
如果不是在activity中创建,需要在前面加上((Activity)mContext). 。
阅读(...) 评论()Android中UI线程与后台线程交互设计的5种方法_西西软件资讯
西西软件下载最安全的下载网站、值得信赖的软件下载站!
→ Android中UI线程与后台线程交互设计的5种方法
1.0.6 官方最新版
类型:图像浏览大小:13.0M语言:英文 评分:4.2
我想关于这个话题已经有很多前辈讨论过了。今天算是一次学习总结吧。在android的设计思想中,为了确保用户顺滑的操作体验。一些耗时的任务不能够在UI线程中运行,像访问网络就属于这类任务。因此我们必须要重新开启一个后台线程运行这些任务。然而,往往这些任务最终又会直接或者间接的需要访问和控制UI控件。例如访问网络获取数据,然后需要将这些数据处理显示出来。就出现了上面所说的情况。原本这是在正常不过的现象了,但是android规定除了UI线程外,其他线程都不可以对那些UI控件访问和操控。为了解决这个问题,于是就引出了我们今天的话题。Android中后台线程如何与UI线程交互。据我所知android提供了以下几种方法,用于实现后台线程与UI线程的交互。1、handler2、Activity.runOnUIThread(Runnable)3、View.Post(Runnable)4、View.PostDelayed(Runnabe,long)5、AsyncTask方法一:handlerhandler是android中专门用来在线程之间传递信息类的工具。要讲明handler的用法非常简单,但是我在这里会少许深入的讲一下handler的运行机制。为了能够让handler在线程间传递消息,我们还需要用到几个类。他们是looper,messageQueue,message。这里说的looper可不是前段时间的好莱坞大片环形使者,他的主要功能是为特定单一线程运行一个消息环。一个线程对应一个looper。同样一个looper对应一个线程。这就是所谓的特定单一。一般情况下,在一个线程创建时他本身是不会生产他特定单一的looper的(主线程是个特例)。因此我们需要手动的把一个looper与线程相关联。其方法只需在需要关联的looper的线程中调用Looper.prepare。之后我们再调用Looper.loop启动looper。说了这么多looper的事情,到底这个looper有什么用哪。其实之前我们已经说到了,他是为线程运行一个消息环。具体的说,在我们将特定单一looper与线程关联的时候,looper会同时生产一个messageQueue。他是一个消息队列,looper会不停的从messageQuee中取出消息,也就是message。然后线程就会根据message中的内容进行相应的操作。那么messageQueue中的message是从哪里来的哪?那就要提到handler了。在我们创建handler的时候,我们需要与特定的looper绑定。这样通过handler我们就可以把message传递给特定的looper,继而传递给特定的线程。在这里,looper和handler并非一一对应的。一个looper可以对应多个handler,而一个handler只能对应一个looper(突然想起了一夫多妻制,呵呵)。这里补充一下,handler和looper的绑定,是在构建handler的时候实现的,具体查询handler的构造函数。在我们创建handler并与相应looper绑定之后,我们就可以传递message了。我们只需要调用handler的sendMessage函数,将message作为参数传递给相应线程。之后这个message就会被塞进looper的messageQueue。然后再被looper取出来交给线程处理。这里要补充说一下message,虽然我们可以自己创建一个新的message,但是更加推荐的是调用handler的obtainMessage方法来获取一个message。这个方法的作用是从系统的消息池中取出一个message,这样就可以避免message创建和销毁带来的资源浪费了(这也就是算得上重复利用的绿色之举了吧)。突然发现有一点很重要的地方没有讲到,那就是线程从looper收到message之后他是如何做出响应的嘞。其实原来线程所需要做出何种响应需要我们在我们自定义的handler类中的handleMessage重构方法中编写。之后才是之前说的创建handler并绑定looper。好吧说的可能哟点乱,总结一下利用handler传递信息的方法。假设A线程要传递信息给B线程,我们需要做的就是1、在B线程中调用Looper.prepare和Looper.loop。(主线程不需要)2、 编写Handler类,重写其中的handleMessage方法。3、创建Handler类的实例,并绑定looper4、调用handler的sentMessage方法发送消息。到这里,我们想handler的运行机制我应该是阐述的差不多了吧,最后再附上一段代码,供大家参考。&1&public&class&MyHandlerActivity&extends&Activity&{
&2&&&&&&TextView&textV
&3&&&&&&MyHandler&myH
&5&&&&&&protected&void&onCreate(Bundle&savedInstanceState)&{
&6&&&&&&&&&&super.onCreate(savedInstanceState);
&7&&&&&&&&&&setContentView(R.layout.handler);
&9&&&&&&&&&&//实现创建handler并与looper绑定。这里没有涉及looper与
&&&&&&&&&&&&//线程的关联是因为主线程在创建之初就已有looper
10&&&&&&&&&&myHandler=MyHandler(MyHandlerActivitythis.getMainLooper());
11&&&&&&&&&&textView&=&(textView)&findViewById(R.id.textView);
12&&&&&&&&&
13&&&&&&&&&&MyThread&m&=&new&MyThread();
14&&&&&&&&&&new&Thread(m).start();
18&&&&&&class&MyHandler&extends&Handler&{
19&&&&&&&&&&public&MyHandler()&{
20&&&&&&&&&&}
22&&&&&&&&&&public&MyHandler(Looper&L)&{
23&&&&&&&&&&&&&&super(L);
24&&&&&&&&&&}
26&&&&&&&&&&//&必须重写这个方法,用于处理message
27&&&&&&&&&&@Override
28&&&&&&&&&&public&void&handleMessage(Message&msg)&{
29&&&&&&&&&&&&&&//&这里用于更新UI
30&&&&&&&&&&&&&&Bundle&b&=&msg.getData();
31&&&&&&&&&&&&&&String&color&=&b.getString(&color&);
32&&&&&&&&&&&&&&MyHandlerActivity.this.textView.setText(color);
33&&&&&&&&&&}
36&&&&&&class&MyThread&implements&Runnable&{
37&&&&&&&&&&public&void&run()&{
38&&&&&&&&&&&&&&//从消息池中取出一个message
39&&&&&&&&&&&&&&Message&msg&=&myHandler.obtainMessage();
40&&&&&&&&&&&&&&//Bundle是message中的数据
41&&&&&&&&&&&&&&Bundle&b&=&new&Bundle();
42&&&&&&&&&&&&&&b.putString(&color&,&&我的&);
43&&&&&&&&&&&&&&msg.setData(b);
44&&&&&&&&&&&&&&//传递数据
45&&&&&&&&&&&&&&myHandler.sendMessage(msg);&//&向Handler发送消息,更新UI
46&&&&&&&&&&}
47&&&&&&}方法二:Activity.runOnUIThread(Runnable)&这个方法相当简单,我们要做的只是以下几步1、编写后台线程,这回你可以直接调用UI控件2、创建后台线程的实例3、调用UI线程对应的Activity的runOnUIThread方法,将后台线程实例作为参数传入其中。注意:无需调用后台线程的start方法方法三:View.Post(Runnable)&该方法和方法二基本相同,只是在后台线程中能操控的UI控件被限制了,只能是指定的UI控件View。方法如下1、编写后台线程,这回你可以直接调用UI控件,但是该UI控件只能是View2、创建后台线程的实例3、调用UI控件View的post方法,将后台线程实例作为参数传入其中。方法四:View.PostDelayed(Runnabe,long)该方法是方法三的补充,long参数用于制定多少时间后运行后台进程&方法五:AsyncTaskAsyncTask是一个专门用来处理后台进程与UI线程的工具。通过AsyncTask,我们可以非常方便的进行后台线程和UI线程之间的交流。那么AsyncTask是如何工作的哪。AsyncTask拥有3个重要参数1、Params&2、Progress3、ResultParams是后台线程所需的参数。在后台线程进行作业的时候,他需要外界为其提供必要的参数,就好像是一个用于下载图片的后台进程,他需要的参数就是图片的下载地址。Progress是后台线程处理作业的进度。依旧上面的例子说,就是下载图片这个任务完成了多少,是20%还是60%。这个数字是由Progress提供。Result是后台线程运行的结果,也就是需要提交给UI线程的信息。按照上面的例子来说,就是下载完成的图片。AsyncTask还拥有4个重要的回调方法。1、onPreExecute2、doInBackground3、onProgressUpdate4、onPostExecuteonPreExecute运行在UI线程,主要目的是为后台线程的运行做准备。当他运行完成后,他会调用doInBackground方法。doInBackground运行在后台线程,他用来负责运行任务。他拥有参数Params,并且返回Result。在后台线程的运行当中,为了能够更新作业完成的进度,需要在doInbackground方法中调用PublishProgress方法。该方法拥有参数Progress。通过该方法可以更新Progress的数据。然后当调用完PublishProgress方法,他会调用onProgressUpdate方法用于更新进度。onProgressUpdate运行在UI线程,主要目的是用来更新UI线程中显示进度的UI控件。他拥有Progress参数。在doInBackground中调用PublishProgress之后,就会自动调onProgressUpdate方法onPostExecute运行在UI线程,当doInBackground方法运行完后,他会调用onPostExecute方法,并传入Result。在onPostExecute方法中,就可以将Result更新到UI控件上。明白了上面的3个参数和4个方法,你要做的就是1、编写一个继承AsyncTask的类,并声明3个参数的类型,编写4个回调方法的内容。2、然后在UI线程中创建该类(必须在UI线程中创建)。3、最后调用AsyncTask的execute方法,传入Parmas参数(同样必须在UI线程中调用)。这样就大功告成了。另外值得注意的2点就是,千万不要直接调用那四个回调方法。还有就是一个AsyncTask实例只能执行一次,否则就出错哦。以上是AsyncTask的基本用法,更加详细的内容请参考android官方文档。最后附上一段代码,供大家参考。&1&private&class&DownloadFilesTask&extends&AsyncTask&URL,&Integer,&Long&&
&2&//在这里声明了Params、Progress、Result参数的类型
&4&&&&&//因为这里不需要使用onPreExecute回调方法,所以就没有加入该方法
&6&&&&&//后台线程的目的是更具URL下载数据
&7&&&&&&protected&Long&doInBackground(URL...&urls)&{
&8&&&&&&&&&&int&count&=&urls.//urls是数组,不止一个下载链接
&9&&&&&&&&&&long&totalSize&=&0;//下载的数据
10&&&&&&&&&&for&(int&i&=&0;&i&&&&i++)&{
11&&&&&&&&&&&&&&//Download是用于下载的一个类,和AsyncTask无关,大家可以忽略他的实现
12&&&&&&&&&&&&&&totalSize&+=&Downloader.downloadFile(urls[i]);
13&&&&&&&&&&&&&&publishProgress((int)&((i&/&(float)&count)&*&100));//更新下载的进度
14&&&&&&&&&&&&&&//&Escape&early&if&cancel()&is&called
15&&&&&&&&&&&&&&if&(isCancelled())&
16&&&&&&&&&&}
17&&&&&&&&&&return&totalS
20&&&&&&//更新下载进度
21&&&&&&protected&void&onProgressUpdate(Integer...&progress)&{
22&&&&&&&&&&setProgressPercent(progress[0]);
25&&&&&&//将下载的数据更新到UI线程
26&&&&&&protected&void&onPostExecute(Long&result)&{
27&&&&&&&&&&showDialog(&Downloaded&&&+&result&+&&&bytes&);
30&有了上面的这个类,接下你要做的就是在UI线程中创建实例,并调用execute方法,传入URl参数就可以了。这上面的5种方法各有优点。但是究其根本,其实后面四种方法都是基于handler方法的包装。在一般的情形下后面四种似乎更值得推荐。但是当情形比较复杂,还是推荐使用handler。最后补充一下,这是我的第一篇博客。存在很多问题请大家多多指教。尤其是文中涉及到内容,有严重的技术问题,大家一定要给我指明啊。拜托各位了。
04-2504-2504-2504-2104-1504-1504-1304-1304-1204-08
阅读本文后您有什么感想? 已有23人给出评价!
名称大小下载更新UI之 runOnUiThread方法简述 - 简书
更新UI之 runOnUiThread方法简述
众所周知,在非主线程中更新UI会发生ANR,所以通常使用handler。在Activity.onCreate中创建一个Handler类的实例,在这个Handler实例的handleMessage回调函数中调用更新界面显示的函数。
还有一种封装好的方法:runOnUiThread:此为点击webview,然后webview中的javasrcipt调用本地java函数,更新UI的例子:
public void startFunction() {
runOnUiThread(new Runnable() {
public void run() {
msgView.setText(msgView.getText() + "\njs调用了java函数");
把更新ui的代码创建在Runnable中,然后在需要更新ui时,把这个Runnable对象传给runOnUiThread(Runnable)。 这样Runnable对像就能在ui程序中被调用。如果当前线程是UI线程,那么行动是立即执行。如果当前线程不是UI线程,操作是发布到事件队列的UI线程。其实和handler差不多,都是将这个更新UI的请求消息,加入到事件队列,等待主线程空闲的时候执行。
奶爸程序员,坐标苏州
/Jasonchenlijian今天看到了一个runOnUiThread()方法用来更新UI,觉得很神奇!!
方法一:handler机制不说了。
方法二:利用Activity.runOnUiThread(Runnable)把更新ui的代码创建在Runnable中,然后在需要更新ui时,把这个Runnable对象传给Activity.runOnUiThread(Runnable)。 这样Runnable对像就能在ui程序中被调用。如果当前线程是UI线程,那么行动是立即执行。如果当前线程不是UI线程,操作是发布到事件队列的UI线程
FusionField.currentActivity.runOnUiThread(new Runnable()
public void run()
Toast.makeText(getApplicationContext(), , "Update My UI",
Toast.LENGTH_LONG).show();
public final void&runOnUiThread&(&action)
action &&the action to run on the UI thread
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);//将Runnable Post到消息队列,由内部的mHandler来处理,实际上也是Handler的处理方式
action.run();//已经在UI线程,直接运行。
参考地址:
阅读(...) 评论()在android 中我们一般用 Handler 做主线程 和 子线程 之间的通信 。
现在有了一种更为简洁的写法,就是 Activity 里面的&runOnUiThread( Runnable )方法。
利用Activity.runOnUiThread(Runnable)把更新ui的代码创建在Runnable中,然后在需要更新ui时,把这个Runnable对象传给Activity.runOnUiThread(Runnable)。&
Runnable对像就能在ui程序中被调用。如果当前线程是UI线程,那么行动是立即执行。如果当前线程不是UI线程,操作是发布到事件队列的UI线程。
package com.
import android.os.B
import android.support.v7.app.AppCompatA
import android.widget.T
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建一个线程
new Thread(new Runnable() {
public void run() {
//延迟两秒
Thread.sleep( 2000 );
} catch (InterruptedException e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(MainActivity.this, "hah", Toast.LENGTH_SHORT).show();
}).start();
&Activity的runOnUiThread(Runnable)
* Runs the specified action on the UI thread. If the current thread is the UI
* thread, then the action is executed immediately. If the current thread is
* not the UI thread, the action is posted to the event queue of the UI thread.
* @param action the action to run on the UI thread
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
action.run();
阅读(...) 评论()

我要回帖

更多关于 new thread runnable 的文章

 

随机推荐