[Android]异常处理 Only the original thread that created a view hierarchy can touch its views

 Java Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Android进阶——Handler的应用之解决Only the original thread that created a view hierarchy can touch its views

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

为什么会有这种异常产生呢?

当每个应用程序apk第一次启动时,Android会同时启动一个对应的主线程(Main Thread),
主线程负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,
并把相关的事件分发到对应的组件进行处理,所以主线程通常又被叫做UI线程。

但是在开发Android应用时必须遵守单线程模型的原则:
Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行,如果在非UI线程中直接操作UI线程,
会抛出android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that
created a view hierarchy can touch its views, 这与普通的java程序不同。
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
由于UI线程负责事件的监听和绘图,因此,必须保证UI线程能够随时响应用户的需求,
UI线程里的操作应该向中断事件那样短小,费时的操作(如网络连接)需要另开线程,
否则,如果UI线程超过5s没有响应用户请求,会弹出对话框提醒用户终止应用程序(ANP)。

如果在新开的线程中需要对UI进行设定,就可能违反单线程模型,
因此android采用一种的Message Queue机制保证线程间通信。

Message Queue是一个消息队列,用来存放通过Handler发送的消息。

Android在第一启动程序时会默认会为UI thread创建一个关联的消息队列,
可以通过Looper.myQueue()得到当前线程的消息队列,用来管理程序的一些上层组件,
activities,broadcast receivers 等,你可以在自己的子线程中创建Handler与UI thread通讯。

Handler会向message queue通过两种方法发送消息:send或post。
这两种消息都会插在message queue队尾并按先进先出执行,
但通过这两种方法发送的消息执行的方式略有不同:
1)通过send发送的是一个message对象, 会被handler的 handleMessage()函数处理;
2)而通过post方法发送的是一个runnable对象,则会自己执行。

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Android系统中的视图组件并不是线程安全的,如果要更新视图,必须在主线程中更新,不可以在子线程中执行更新的操作。
既然这样,我们就在子线程中通知主线程,让主线程做更新操作吧。那么,我们如何通知主线程呢?
我们需要使用到Handler对象。
代码如下:
 Java Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public  class MainActivity  extends Activity  implements View.OnClickListener
{

     private  static  final  int COMPLETED =  0;

     private TextView stateText;
     private Button btn;

     private Handler handler =  new Handler()
    {
        @Override
         public  void handleMessage(Message msg)
        {
             if (msg.what == COMPLETED)
            {
                stateText.setText( "completed");
            }
        }
    };

    @Override
     public  void onCreate(Bundle savedInstanceState)
    {
         super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        stateText = (TextView) findViewById(R.id.tv);
        btn = (Button) findViewById(R.id.btn);

        btn.setOnClickListener( this);
    }

    @Override
     public  void onClick(View v)
    {
         new WorkThread().start();
    }

     //工作线程
     private  class WorkThread  extends Thread
    {
        @Override
         public  void run()
        {
             //......处理比较耗时的操作

             //处理完成后给handler发送消息
            Message msg =  new Message();
            msg.what = COMPLETED;
            handler.sendMessage(msg);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值