第10讲UI线程阻塞及其优化

、UI
阻塞demo

(首先在activity_main.xml中放置两个button,分别命名为button1,button2)

//首先设置一个button1用来进行动画演示

Button button1=(Button) findViewById(R.id.button1);

//位移方向移动的动画

TranslateAnimation animation=new TranslateAnimation(100,150, 50, 100);

animation.setDuration(2000);                 //设置持续的时间,单位为微秒

animation.setRepeatCount(10);             //设置重复的次数

button1.setAnimation(animation);

//设置一个button2进行耗时操作sleep

Button button2=(Button) findViewById(R.id.button2);

button2.setOnClickListener(new OnClickListener(){

public void onClick(View v) {

try {

Thread.sleep(5000);                                    //设置线程耗时操作,单位ms

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

点击button2之后,button1的移动发生卡死,发生UI线程阻塞。

当一个应用程序启动之后,Android系统会为这个应用程序创建一个主线程。这个线程非常重要,它负责渲染视图,分发事件到响应监听器并执行,对界面进行轮询监听。因此,一般也叫做“UI线程”。

Android系统不会给应用程序的多个元素组件,建立多个线程来执行。一个视图(activity)中的多个view组件运行在同一个UI线程当中。因此多个view组件的监听器的执行可能对相互影响(即是UI线程阻塞)

、UI阻塞解决方案:创建一个新线程

Button button2 = (Button)findViewById(R.id.button2);

button2.setOnClickListener(new OnClickListener(){

public void onClick(View v) {

new Thread(newRunnable() {                 //创建一个新线程

public void run() {

try {

Thread.sleep(5000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}).start();

}

});

将耗时操作放在一个新的线程里面进行操作,利用new Thread().start()打开新的线程。

此时因为没有更改view,所以不会报错。但是一旦我们在UI线程外修改了view组件的属性,则会报错。

安卓官方规定的两个规则

There are two simple rules to Android’ssingle thread model:

Do not block the UI thread. 不要阻塞UI线程

Do not access the Android UI toolkit from outside of the UIthread. 不要再UI线程之外的其他线程中,对视图当中的组件进行设置

违反rule2会报异常:Only the original thread that created aview hierarchy can touch its views.

、在其他的线程中修改UI线程中的组件

方法a:view.post

将需要进行view组件修改的程序部分放在v.post(new Runnable() { }中的run()方法进行即可。

Buttonbutton2 = (Button) findViewById(R.id.button2);

button2.setOnClickListener(newOnClickListener() {

publicvoid onClick(final View v) {

newThread(newRunnable() {

publicvoid run() {

try {

Thread.sleep(5000);      //设置线程耗时操作,单位ms。在新线程中进行耗时操作

} catch (InterruptedException e){

e.printStackTrace();

}

} .

}).start();

intsum=10;                         //假定通过耗时操作计算处理的得到的一个值

v.post(newRunnable() {

public void run() {

TextView textView=(TextView) v;         //在post中进行view修改操作

textView.setText(""+10);

}

});

}

});

post原理:通过view.post在任务队列中添加一个任务Runnable对象,UI thread在轮询过程中会检查任务队列中是否有任务,有则执行(如下图所示)。此时任务队列中的修改view组件的操作是在UI线程中执行的,则不违反上面的rule2.

方案a:post方法,可读性差,维护性差。

原理是在新线程中进行耗时操作,在post中进行view修改操作。

方法b:AsyncTask (异步任务)

AsyncTask允许你在你的用户接口上执行异步工作。他在工作者线程中执行阻塞操作,然后将结果发布给 UI线程,不需要你自己处理线程或者 handler。

为了使用他,你需要继承 AsyncTask并且实现他的 doInBackground()回调方法,他在一个后台线程池中运行。为了更新你的 UI,你需要实现 onPostExecute()方法,他传递来自 doInBackgroud()的结果且在 UI线程中运行。所以你可以安全的更新你的 UI。你可以在 UI线程通过 execute()来运行你的任务。

privateButton button2 = null;

protected voidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//为button1添加一个动画操作

Buttonbutton1 = (Button) findViewById(R.id.button1);

//位移方向移动的动画

TranslateAnimationanimation = new TranslateAnimation(0,150,0,0);

animation.setRepeatCount(30);     //设置重复的次数

animation.setDuration(2000);                  //设置持续的时间,单位为微秒

button1.setAnimation(animation);

button2= (Button) findViewById(R.id.button2);

button2.setOnClickListener(newOnClickListener() {

publicvoid onClick(final View v){

newDownloadImageTask().execute();

}

});

}

privateclass DownloadImageTask extends AsyncTask<String, Void,Integer> {

protected IntegerdoInBackground(String... urls) {

try{

Thread.sleep(5000);

}catch (InterruptedException e) {

e.printStackTrace();

}

intsum=10;

returnsum;

}

protected voidonPostExecute(Integer sum) {

button2.setText(""+sum);

}

}

第10讲- UI线程阻塞及其优化的更多相关文章

  1. Android Studio学习随笔-UI线程阻塞以及优化

    我们在使用手机的时候,经常会遇到一个问题:先是卡死,然后跳出该程序无响应,是否关闭的提示(当然有可能是我们手机性能太差=.=)这是因为线程的阻塞引起的,在这里我讲述一下UI线程,一般处理程序会在UI线 ...

  2. jQuery同步Ajax带来的UI线程阻塞问题及解决办法

    俗话说不作死就不会死,今天作死了一回,写了一个比较二逼的函数,遇到了同步Ajax引起的UI线程阻塞问题,在此记录一下. 事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的原则 ...

  3. jQuery同步Ajax带来的UI线程阻塞问题及解决方法

    遇到了同步Ajax引起的UI线程阻塞问题,在此记录一下. 事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的原则,我封装了一个名为getData的函数,它接收不同参数,只负责 ...

  4. jQuery同步Ajax带来的UI线程阻塞问题

    一.需求 在调ajax接口的时候因为有时间延迟,想要做一个loading加载的效果,等数据返回时再把loading的效果去掉. 所以我在调ajax的代码块前面加了显示loading效果的代码,ajax ...

  5. Jquery ajax 同步阻塞引起的UI线程阻塞的坑(loading图片显示不出来,layer.load延迟)

    今天想做一个点击地市用ajax重新获取数据刷新页面功能,因为ajax属于耗时操作,想在获取数据且加载页面时显示加载遮罩层,结果发现了ajax的好多坑. 例如如上栗子,我想点击按钮让遮罩层显示,ajax ...

  6. Javascript之UI线程与性能优化

    在浏览器中,Javascript执行与UI更新是发生在同一个进程(浏览器UI线程)中的.UI线程的工作基于一个简单的队列系统,任务会被保存到队列中直到进程空闲时被提取出来执行.所以Javascript ...

  7. [ionic开源项目教程] - 第10讲 新闻详情页的用户体验优化

    目录 [ionic开源项目教程] 第1讲 前言,技术储备,环境搭建,常用命令 [ionic开源项目教程] 第2讲 新建项目,架构页面,配置app.js和controllers.js [ionic开源项 ...

  8. 通过使用Web Workers,Web应用程序可以在独立于主线程的后台线程中,运行一个脚本操作。这样做的好处是可以在独立线程中执行费时的处理任务,从而允许主线程(通常是UI线程)不会因此被阻塞/放慢。

    Web Workers API - Web API 接口参考 | MDNhttps://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API ...

  9. C#.NET使用Task,await,async,异步执行控件耗时事件(event),不阻塞UI线程和不跨线程执行UI更新,以及其他方式比较

    使用Task,await,async,异步执行事件(event),不阻塞UI线程和不跨线程执行UI更新 使用Task,await,async 的异步模式 去执行事件(event) 解决不阻塞UI线程和 ...

随机推荐

  1. 用java流方式判断文件类型

    这个方法只能在有限的范围内有效.并不是万金油 比如 图片类型判断,音频文件格式判断,视频文件格式判断等这种肯定是2进制且专业性很强的文件类型判断. 下面给出完整版代码 首先是文件类型枚取 packag ...

  2. mysql 获取当前时间戳

      mysql 获取当前时间为select now() 运行结果: 2012-09-05 17:24:15 mysql 获取当前时间戳为select unix_timestamp(now()) 运行结 ...

  3. 斐波那契数列 Php练手

    数列从第三项开始,每一项都等于前两项之和. F0=0,F1=1,Fn=F(n-1)+F(n-2) 递归版和非递归版. <?php function fib($n){ $array = array ...

  4. Android 按二次后退键退出应用程序

    前言          欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载,但请保留文章原始出处:          CSDN:http://www.csdn.net        ...

  5. 在sae配置django项目

    1:使用sae开发必须有sae帐号,自己注册吧: 2:在sae上新建立一个python项目: 3:建立完成之后新建一个版本,即版本1: 4:获取svn的地址在eclipse中check下来: 5:注意 ...

  6. unity3d 学习笔记(一)

    操作:按下shit 点击坐标轴中心 切换透视图 动画烘焙的概念:相当于把原来的控制器动画或者IK(骨骼)动画所有塌陷为逐帧动画,导出的时候必须选这一项 着色器:从技术的角度来看,着色器是渲染器的一个部 ...

  7. 你所不知道的java编程思想

    读thinking in java这本书的时候,有这么一句话“在编译单元的内部,可以有一个公共(public)类,它必须拥有与文件相同的名字” 有以下疑问: 在一个类中说可以有一个public类,那是 ...

  8. C#如何获得本地电脑IP

    using System; using System.Collections.Generic; using System.Text; using System.Net;   //需要引用.Net命名空 ...

  9. MySql函数应用

    -- 当前时间 now(); -- 查询结果串联(逗号) select group_concat(col_name) from table_name;

  10. sqlite数据库操作详细介绍 增删改查,游标

    sqlite数据库操作详细介绍 增删改查,游标     本文来源于www.ifyao.com禁止转载!www.ifyao.com Source code     package com.example ...