Android线程大坑

     android界面的更新实在主线程进行的,通常把主线程也叫UI线程,UI线程里进行事件的分发和交互。在UI线程中进行耗时操作,比如网络请求,IO操作等会阻塞UI线程,界面会卡住,并且超过大概5秒钟程序会ANR(Application Not Responding),也就是死掉。其实这种GUI单线程的思想在我上一篇博客(http://zyqwst.iteye.com/blog/2262011)都有阐述,道理一模一样,只是android实现的方式上略有不同,所以我建议把上一篇Swing线程的博客能够阅读一遍,Android线程的问题豁然开朗,始终晋级GUI开发的原则:在UI线程中进行界面的更新操作,在单独线程中进行耗时操作

   同样我们从代码看看如何分离UI更新和耗时操作:点击按钮,10秒钟后按钮显示“点击了”。

public void clickBtn(View v){
		Button btn = (Button) findViewById(R.id.btn);
		try {
			Thread.sleep(10000);//模拟耗时操作
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		btn.setText("点击了");
	}

 运行程序,点击按钮,然后界面卡死,然后10秒后才显示出来,或者直接ANR了。很明显上面的代码违背了GUI单线程的原则,耗时操作应该在单独的线程中进行。

 

 

    既然如此那我们再改良下代码,把操作放到单独线程去

public void clickBtn(View v){
		final Button btn = (Button) findViewById(R.id.btn);
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				btn.setText("点击了");
			}
		}).start();
		
	}

 运行代码,点击按钮,界面没有卡住,还可以操作,然后10秒后按钮上的字改变了,或者你根本看不到直接ANR了。已经放到单独线程了,为啥还有错?因为 btn.setText("点击了");这句代码是更新界面的操作,但是它没有在UI线程中执行,而是在其他线程执行了,还是违背了GUI单线程的原则。

 

 

      然后现在有的童鞋会这样修改代码

public void clickBtn(View v){
		final Button btn = (Button) findViewById(R.id.btn);
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
		btn.setText("点击了");
	}

 把更新界面的操作放在单独线程外,运行代码,点击按钮,立即更新按钮文字。这不是我们的业务了。原因很简单,不再赘述。

       既然都不对,那到底应该怎样修改呢?Android给我们提供了几种方法在耗时线程中更新UI界面。

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable, long)
public void clickBtn(View v){
		final Button btn = (Button) findViewById(R.id.btn);
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				btn.post(new Runnable() {
					public void run() {
						btn.setText("点击了");
					}
				});
			}
		}).start();
		
	}

再次修改代码后运行,符合我们的期望,完美。但是代码却变得很复杂,维护性也变差了。所以,也有了很多其他方式,利用Handler、AsyncTask等,还有第三方的框架等。Handle用法,AsyncTask用法可自行百度

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐
  • —软件人才免语言低担保 赴美带薪读研!—



你可能感兴趣的:(android,线程,大坑)