Android 后台任务(二)Thread And Handler

Android 后台任务(二)Thread And Handler

翻译自:http://blog.stylingandroid.com/archives/833

 转载请注明:http://blog.csdn.net/liaoqianchuan00/article/details/23949545


在之前的文章中我们讲解了为什么我们尽量不要在UI线程中处理一些很慢的事情来阻塞UI线程。这篇文章我们关注如何来做。

 

最简单的处理办法就是使用java线程。将任务处理放在一个线程中是这样的简单。

 

new Thread( new Runnable()

{

    @Override

    public void run()

    {

        // Dosomething

    }

} ).start();

 

将任务放在Runnable中得run方法中,这样就能在一个新线程中执行,并且当任务完成后自动结束线程。

 

我们很快就会遇到问题了。比如下面这个例子:

new Thread( new Runnable()

{

    @Override

    public void run()

    {

        // Dosomething

        TextViewtextView =

            (TextView)findViewById( R.id.textview );

        textView.setText("Hello World" );

    }

} ).start();

 

我们在线程中处理一个耗时操作,在耗时操作结束时,我们改变TextView中的文字。这看起来很好,但是当我们运行他得时候出现了runtime exception:

E/AndroidRuntime(9129): android.view.ViewRootImpl$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views.

 

这个log提示我们如果我们想要去修改一些View(比如说我们例子中得TextView),需要在创建这个View的线程中去做----即我们的老朋友UI线程。这里看起来由点困惑:我们在UI线程之外处理了一些事情,但是我们又需要去在UI线程更新我们的UI。这好像是告诉我们要在UI线程中处理所有的事情,但是我们前面已经讨论了,这不是个好办法。

 

幸运的是,已经有机制让我们回到UI线程去执行代码了。Activity有一个方法叫做runOnUiThread,这可以让我们在UI线程中执行代码

new Thread( new Runnable()

{

    @Override

    public void run()

    {

        // Dosomething

        finalTextView textView =

            (TextView)findViewById( R.id.textview );

        runOnUiThread(new Runnable()

        {

            @Override

            publicvoid run()

            {

                textView.setText("Hello World" );

            }

        } );

    }

} ).start();

 

在Android中,我们还有一种方法:

new Thread( new Runnable()

{

    @Override

    public void run()

    {

        finalTextView textView =

            (TextView)findViewById( R.id.textview );

        textView.post(new Runnable()

        {

            @Override

            publicvoid run()

            {

                textView.setText("Hello World" );

            }

        } );

    }

} ).start();

 

这里我们使用post方法也可以得到和runOnUiThread相同的结果,这个方式一般用在我们可以得到TextView,但是不能得到Activity每个View都有一个在UI线程中处理的messagequeue。Post允许我们向这个message queue发送一个新的message。

 

Message queue机制是通过Handler来实现的,这也就引入了我们要讲的另外一种处理这种耗时操作然后更新UI的方法。UI线程中创建一个我们自己的Handler实例,然后我们可以向这个Handler发送message,这些message会在创建这个Handler的线程中执行

final Handler handler = new Handler();

new Thread( new Runnable()

{

    @Override

    public void run()

    {

        // Dosomething

        finalTextView textView =

            (TextView)findViewById( R.id.textview );

        handler.post(new Runnable()

        {

            @Override

            publicvoid run()

            {

                textView.setText("Hello World" );

            }

        } );

    }

} ).start();

 

注意:Handler在构造的时候会指定一个looper对象,若未指定,就用本线程的。所以当我们在UI线程中创建handler的时候,looper其实是主线程的looper,而一般的工作线程其实没有looper,所以如果我们要在工作线程中去newHandler,我们需要在线程中加入的looper

 

 

而如果我们要不时的更新我们的UI,比如更新ProgressBar,这就意味着我们要不断的切换到UI线程中去更新UI,这会让我们的代码很难看。Android提供了AsyncTask来完成这个工作,我们下节将会讲到这个的用法。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值