关于UI线程的阻塞问题以及处理方式

学习Android,有一条程序设计中比较重要的原则,就是永远不要阻塞UI线程。(以下观点是个人看法,不到之处望大家指出互相学习)

一、什么叫UI线程的阻塞?

UI线程的阻塞是指,由于在activity所在的线程中执行耗时操作,导致UI线程无法正常的运作。

二、UI线程的阻塞会导致什么?

会导致程序发生假死状态,导致用户提前关闭程序,丧失用户数量。或者在过了5秒之后Android系统出来干预,弹出提示框类似”XX程序无响应,是否关闭?“这类的提示框,极大地降低用户的体验。

三、如何防止UI线程的阻塞?

当然是将耗时操作放到其他的线程中。但是话虽然这么说,但是关于这个还值得讨论一下,也是本篇重点

先让我们看看官方的两条规则:

1、不要阻塞UI线程

2、不要在UI线程之外的线程对视图(view)进行任何的设置。

第一条没什么可深究的,主要是在第二条。如果你违反了第二条规则,程序就会抛出异常。也许就这个问题让很多人都很蛋疼。那你肯定会问,如果我想在UI线程之外的执行耗时操作的线程中对视图进行设置怎么办?这两条规则那不就矛盾了吗?

官方也意识到了这一点,所以给我们提供了具体的解决这个问题的两个方法。

方法一、使用view.post()方法看下面的示例代码。

bu.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(final View view) {
					new Thread(new Runnable() {
					@Override
					public void run() {
						//模拟耗时操作
						try {
							Thread.sleep(8000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						view.post(
								new Runnable() {
									
									@Override
									public void run() {
										// TODO Auto-generated method stub
										//模拟对view的设置操作
										view.setBackgroundColor(Color.BLACK);
									}
								}
								);
								
									}	
					}).start();
			}
		});
    }

此方法是将对button的背景颜色的设置放到了post()方法中。此时就解决了前面提到的“矛盾”问题。具体的原理就是在UI线程和耗时线程之间放一个任务队列,UI线程在执行的过程之中会不断地轮询这个任务队列,如果里面有任务就拿出来执行(是在主线程里面执行,也即是说上面例子中对button的设置最终是在主线程里面执行的)。当然如果耗时线程里面有任务,就抛出到消息队列里面。这就形成了一个”生产——消费“模型。从而解决了这个问题。

但是你会发现虽然问题解决了,但是新的问题也就随之产生。这段代码可读性特别差,在程序维护方面做得很不好。别急还有第二个方法。 

方法二、应用AsyncTask.废话不多说直接上代码

 btn=(Button) findViewById(R.id.button1);
        btn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				new MyAsyn().execute();
				
			}
		});
    }
    //睡眠8s,然后传出一个“done”到onPostExecute,在这里设置按钮的名字为“done”
    private class MyAsyn extends AsyncTask<String, Void, String>{
		protected String doInBackground(String... s) {
			// TODO Auto-generated method stub
			try {
				Thread.sleep(8000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return "done";
		}
		protected void onPostExecute(String s) {
			btn.setText(s);
		}
    	
    }
两种犯法其实原理是一样的,都是将耗时操作和对View的设置分开,将耗时操作放在doInBackground,将对view的设置放在onPostExecute。关于Asynctask的相关知识希望会在以后单独摘出来一篇来一起学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值