android菜鸟笔记之UI线程阻塞
来源:互联网 发布:有哪些育儿软件 编辑:程序博客网 时间:2024/05/21 19:46
最近在学习Android,有些还是需要记录下来,方便以后查询
首先
当一个应用程序启动之后,android系统会为这个应用程序创建一个主线程。这个线程非常重要,它负责渲染视图,分发事件到响 应监听器并执行, 对界面进行轮询的监听。因此,一般也叫做“UI”线程。android系统不会给应用程序的多个元素组件,建立多个线程来执行。一个视图(activity)中的多个view组件运行在同一个UI线程当中。因此,多个view组件的监听器的执行可能会相互影响。
例如:当在UI线程当中执行耗时操作,比如访问网络,访问数据库等。则会导致UI线程阻塞。当UI线程阻塞,则屏幕会出现卡死情况。这样用户体验非常差。当线程阻塞超过5秒以后,android系统有可能进行干预,弹出对话框询问是否关闭应用程序。
新建一个android project Application,
打开activity_main.xml,添加button1与button2
在MainActivity.java的onCreate中添加如下代码
@Overrideprotected 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() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubtry {Thread.sleep(5000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.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代码如下:
@Overrideprotected 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() {@Overridepublic void onClick(final View v) {// TODO Auto-generated method stubnew Thread(new Runnable(){@Overridepublic void run() {System.out.println("线程开始");// TODO Auto-generated method stubtry {Thread.sleep(5000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}int i = 20;v.post(new Runnable(){@Overridepublic void run() {System.out.println("post线程开始");// TODO Auto-generated method stubTextView 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;@Overrideprotected 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() {@Overridepublic void onClick(final View v) {// TODO Auto-generated method stubnew 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 blocke.printStackTrace();}int i = 100;return i;}protected void onFostExecute(Integer result){btn2.setText("" + result);}}最终结果:
- android菜鸟笔记之UI线程阻塞
- Android学习:UI线程阻塞
- Android菜鸟学习笔记之---用handler更新UI
- android ui线程阻塞和优化
- Android学习:UI线程阻塞post解决方案
- Android-不阻塞的UI线程方法
- android中用AsyncTask解决UI线程阻塞
- Android之线程阻塞(一)
- UI线程阻塞问题
- Android不阻塞的UI线程的方法
- Android学习:AsyncTask方案解决UI线程阻塞
- android入门(六) UI线程阻塞及其优化
- Android线程—多线程之阻塞队列
- UI线程阻塞及优化
- UI线程阻塞以及优化
- java 多线程学习笔记之 线程实现(线程阻塞)
- android 异步回调中操作UI线程,UI同步、卡死阻塞等性能问题
- Android 异步回调中操作UI线程,UI同步、卡死阻塞等性能问题
- PTAM编译选项
- hdu 1166
- C#关于使用正则表达式解析字符串
- UILabel
- The Dole Queue
- android菜鸟笔记之UI线程阻塞
- 基础线程知识
- C/C++ 类和结构体的差别
- 软件测试面试题—选择题2
- 回环打印
- 【数据库】——ADO的七个对象和4个数据集合
- 并查集
- PHP自定义安装
- Android Studio使用技巧系列教程(七)