android菜鸟笔记之UI线程阻塞
2015-07-29 23:05
405 查看
最近在学习Android,有些还是需要记录下来,方便以后查询
首先
当一个应用程序启动之后,android系统会为这个应用程序创建一个主线程。这个线程非常重要,它负责渲染视图,分发事件到响 应监听器并执行, 对界面进行轮询的监听。因此,一般也叫做“UI”线程。android系统不会给应用程序的多个元素组件,建立多个线程来执行。一个视图(activity)中的多个view组件运行在同一个UI线程当中。因此,多个view组件的监听器的执行可能会相互影响。
例如:当在UI线程当中执行耗时操作,比如访问网络,访问数据库等。则会导致UI线程阻塞。当UI线程阻塞,则屏幕会出现卡死情况。这样用户体验非常差。当线程阻塞超过5秒以后,android系统有可能进行干预,弹出对话框询问是否关闭应用程序。
新建一个android project Application,
打开activity_main.xml,添加button1与button2
在MainActivity.java的onCreate中添加如下代码
点击OK将退出程序
Android提供了两个解决方案给我们
android的UI规则
there are simply two rules to Android's single thread model;
Do not block the UI thread
不要阻塞UI线程
Do not access the Android UI toolkit from outside the UI thread
不要在UI线程之外的其他线程中,对视图当中的组件进行设置
//经典异常:
Only the original thread that created a view hierarchy can touch its views.
只有创建view的那个线程才能对其进行修改
解决方案1:post
调整onCreate代码如下:
在日志中看到它把修改Button2的放到了主控制之后执行,但其实Post操作还是在主线程中的,并不是新建一个线程进行操作。
而且Sleep(5000)变成了只针对Button2执行。之前是对全局进行操作。
如图:其实View.Post方式,类似于生产者与消费者的模式。每次UI线程都会在任务队列中查找一次操作,同时View.Post在里面放入自己的操作。
以上代码相当复杂,可读性差,所以官方提供了另一个方法来处理这种问题。
解决方案2:AsyncTask
官方提供了以下片段:
由于要写一个内部类所以需要定义全局变量
private Button btn2 = null;
修改代码如下
首先
当一个应用程序启动之后,android系统会为这个应用程序创建一个主线程。这个线程非常重要,它负责渲染视图,分发事件到响 应监听器并执行, 对界面进行轮询的监听。因此,一般也叫做“UI”线程。android系统不会给应用程序的多个元素组件,建立多个线程来执行。一个视图(activity)中的多个view组件运行在同一个UI线程当中。因此,多个view组件的监听器的执行可能会相互影响。
例如:当在UI线程当中执行耗时操作,比如访问网络,访问数据库等。则会导致UI线程阻塞。当UI线程阻塞,则屏幕会出现卡死情况。这样用户体验非常差。当线程阻塞超过5秒以后,android系统有可能进行干预,弹出对话框询问是否关闭应用程序。
新建一个android project Application,
打开activity_main.xml,添加button1与button2
在MainActivity.java的onCreate中添加如下代码
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建动画按钮 Button btn1 = (Button)findViewById(R.id.button1); TranslateAnimation translateAnimation = new TranslateAnimation(0, 150, 0, 0); translateAnimation.setRepeatCount(30);//运行次数 translateAnimation.setDuration(2000);//设置越少运动速度越快 btn1.setAnimation(translateAnimation); Button btn2 = (Button)findViewById(R.id.button2); btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); }启动运行,当我们点击Button2后,等待片刻后尝试再点击会出现以下
点击OK将退出程序
Android提供了两个解决方案给我们
android的UI规则
there are simply two rules to Android's single thread model;
Do not block the UI thread
不要阻塞UI线程
Do not access the Android UI toolkit from outside the UI thread
不要在UI线程之外的其他线程中,对视图当中的组件进行设置
//经典异常:
Only the original thread that created a view hierarchy can touch its views.
只有创建view的那个线程才能对其进行修改
解决方案1:post
调整onCreate代码如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建动画按钮 Button btn1 = (Button)findViewById(R.id.button1); TranslateAnimation translateAnimation = new TranslateAnimation(0, 150, 0, 0); translateAnimation.setRepeatCount(30);//运行次数 translateAnimation.setDuration(2000);//设置越少运动速度越快 btn1.setAnimation(translateAnimation); Button btn2 = (Button)findViewById(R.id.button2); btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(final View v) { // TODO Auto-generated method stub new Thread(new Runnable(){ @Override public void run() { System.out.println("线程开始"); // TODO Auto-generated method stub try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } int i = 20; v.post(new Runnable(){ @Override public void run() { System.out.println("post线程开始"); // TODO Auto-generated method stub TextView tView = (TextView)v; tView.setText("" + 100); } }); System.out.println("线程结束"); } }).start(); } }); }
在日志中看到它把修改Button2的放到了主控制之后执行,但其实Post操作还是在主线程中的,并不是新建一个线程进行操作。
而且Sleep(5000)变成了只针对Button2执行。之前是对全局进行操作。
如图:其实View.Post方式,类似于生产者与消费者的模式。每次UI线程都会在任务队列中查找一次操作,同时View.Post在里面放入自己的操作。
以上代码相当复杂,可读性差,所以官方提供了另一个方法来处理这种问题。
解决方案2:AsyncTask
官方提供了以下片段:
private class DownloadImageTask extends AsyncTask<string void="" bitmap="">{ /*the system calls this to perform work in a workerdelivers it the parameters given to AsyncTask.execute()*/ protected Bitmap doInBackground(String... urls){ return loadImageFromNetwork(urls[0]); } /*The system calls this to perform work in the UI thread and delivers* the result from doInBackground()*/ protected void onFostExecute(Bitmap result){ mImageView.setImageBitmap(result); } } </string>
由于要写一个内部类所以需要定义全局变量
private Button btn2 = null;
修改代码如下
private Button btn2 = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建动画按钮 Button btn1 = (Button)findViewById(R.id.button1); TranslateAnimation translateAnimation = new TranslateAnimation(0, 150, 0, 0); translateAnimation.setRepeatCount(30);//运行次数 translateAnimation.setDuration(2000);//设置越少运动速度越快 btn1.setAnimation(translateAnimation); btn2 = (Button)findViewById(R.id.button2); btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(final View v) { // TODO Auto-generated method stub new ChangeButtonText().execute(); } }); } private class ChangeButtonText extends AsyncTask<String, Void, Integer>{ protected Integer doInBackground(String... urls){ try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } int i = 100; return i; } protected void onFostExecute(Integer result){ btn2.setText("" + result); } }最终结果:
相关文章推荐
- Unable to build the default ValidatorFactory
- codeforce Gym 100570B ShortestPath Query (最短路SPFA)
- easyui的datebox限定范围
- QuickContackBadge学习笔记
- serialVersionUID 的作用
- UIButton
- GCD介绍(一):基本概念和Dispatch Queue
- UIView属性学习
- CF_484B_MaximumValue
- iOS"Request failed: unacceptable content-type: text/html"
- CF_288B_PoloThePenguinAndHouses
- UIView
- UI的类--UIView
- 使用JS给value属性赋值的实例
- The Dole Queue
- UILabel
- vector\list\deque的选取
- [iOS]UILable文字如何在顶部
- UI04_UIButton
- CharSequence与String区别