10 UI线程阻塞及其优化

1、button1移动30次的小动画:

Ui_thread01Activity.java:

public class Ui_thread01Activity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //为button1添加一个动画
        Button button1=(Button)findViewById(R.id.button1);
        //类似jQuery中的animate方法
        TranslateAnimation animation=new  TranslateAnimation(0,150,0,0);//在x轴上移动150
        animation.setRepeatCount(30);//重复30次
        animation.setDuration(2000);//设置动画经历时间
        button1.setAnimation(animation);
    }

}

运行结果:button1不停在移动,移动30次


2、button1移动30次时,button2也有相应事件的小动画:

Ui_thread01Activity.java:

public class Ui_thread01Activity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //为button1添加一个动画
        Button button1=(Button)findViewById(R.id.button1);
        //类似jQuery中的animate方法
        TranslateAnimation animation=new  TranslateAnimation(0,150,0,0);//在x轴上移动150
        animation.setRepeatCount(30);//重复30次
        animation.setDuration(2000);//设置动画经历时间
        button1.setAnimation(animation);

        //为button2添加相应事件
        Button button2=(Button)findViewById(R.id.button2);
        button2.setOnClickListener(new OnClickListener(){
            public void onClick(View v) {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        });
    }

}

运行结果:

一开始button一直在做平移运动,当点击button2时,button1就停止运动,过一段时间之后,button1继续运动直到30次结束;


Main thread(UI thread)

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

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

例如:当在ui线程中执行耗时操作,比如访问网络,访问数据库等。则会导致UI线程阻塞。当UI线程阻塞,则屏幕会出现卡死情况。这样用户体验非常差。当线程阻塞超过5秒以后,Android系统有可能进行干预,弹出对话框询问是否关闭应用程序。


例如,当我们把button2的相应事件中时间改为50秒;那么此时系统会自行进行干预:

代码:Thread.sleep(50000);

运行结果:


如何让程序不引起阻塞;解决方案:

1、创建一个新的线程;

代码:

public class Ui_thread01Activity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //为button1添加一个动画
        Button button1=(Button)findViewById(R.id.button1);
        //类似jQuery中的animate方法
        TranslateAnimation animation=new  TranslateAnimation(0,150,0,0);//在x轴上移动150
        animation.setRepeatCount(30);//重复30次
        animation.setDuration(2000);//设置动画经历时间
        button1.setAnimation(animation);

        //为button2添加相应事件
        Button button2=(Button)findViewById(R.id.button2);
        button2.setOnClickListener(new OnClickListener(){
            public void onClick(View v) {
                //创建一个新的线程
                new Thread(new Runnable(){
                    public void run() {
                        try {
                            Thread.sleep(50000);
                        }catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();;

            }

        });
    }

}

运行效果:(当button2点击的时候,不会停止button1的移动)

2、然而会有新的问题发生;

官方规则:

把上面setOnClickListener的代码改成:

会产生问题的代码:

button2.setOnClickListener(new OnClickListener(){
            public void onClick(final View v) {
                //创建一个新的线程
                new Thread(new Runnable(){
                    public void run() {
                        try {
                            Thread.sleep(50000);
                        }catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //执行之后把button2上面的字改成10
                        int sum=10;//通过耗时操作计算处理一个值
                        TextView view = (TextView) v;
                        view.setText(""+10);

                    }
                }).start();;

            }

        });

运行结果:

对此问题的解决措施:

1、用解决方案1:view.post:

原理图:

public class Ui_thread01Activity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //为button1添加一个动画
        Button button1=(Button)findViewById(R.id.button1);
        //类似jQuery中的animate方法
        TranslateAnimation animation=new  TranslateAnimation(0,150,0,0);//在x轴上移动150
        animation.setRepeatCount(30);//重复30次
        animation.setDuration(2000);//设置动画经历时间
        button1.setAnimation(animation);

        //为button2添加相应事件
        Button button2=(Button)findViewById(R.id.button2);
        button2.setOnClickListener(new OnClickListener(){
            public void onClick(final View v) {
                //创建一个新的线程
                new Thread(new Runnable(){
                    public void run() {
                        Log.i("myinfo", "线程开始执行!!!");
                        try {
                            Thread.sleep(5000);
                        }catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //执行之后把button2上面的字改成10
                        int sum=10;//通过耗时操作计算处理一个值

                        v.post(new Runnable(){
                            public void run() {
                                Log.i("myinfo", "post开始执行!!!");
                                TextView view = (TextView) v;
                                view.setText(""+10);
                            }
                        });
                        Log.i("myinfo", "线程执行结束!!!");
                    }
                }).start();;

            }

        });
    }

}

运行结果:点击button2之后,过一段时间,button2会变成10,不会产生阻塞。

LogCat显示情况:

次解决方法的缺点:

可读性差,维护性差;

2、用解决方案2:AsyncTask:(最佳解决方案)

异步:此方法写法与view.post相同,只是将方法进行了封装。

分成后台执行的耗时任务和与UI组件进行交互的任务;

代码:

public class Ui_thread01Activity extends Activity {
    Button button2=null;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //为button1添加一个动画
        Button button1=(Button)findViewById(R.id.button1);
        //类似jQuery中的animate方法
        TranslateAnimation animation=new  TranslateAnimation(0,150,0,0);//在x轴上移动150
        animation.setRepeatCount(30);//重复30次
        animation.setDuration(2000);//设置动画经历时间
        button1.setAnimation(animation);

        //为button2添加相应事件
        Button button2=(Button)findViewById(R.id.button2);
        button2.setOnClickListener(new OnClickListener(){
            public void onClick(final View v) {
                //执行,创建Task对象
                new DownloadImageTask().execute();

            }
        });
    }

    private class DownloadImageTask extends AsyncTask<String, Void, Integer>{
        @Override
        protected Integer doInBackground(String...urls ) {
           try{
               Thread.sleep(5000);
           }catch(InterruptedException e){
               e.printStackTrace();
           }
           int sum=10;
           return sum;
        }
        @Override
        protected void onPostExecute(Integer sum) {
            button2.setText(""+sum);
        }
    }

}

运行结果:

时间: 2024-08-29 10:29:01

10 UI线程阻塞及其优化的相关文章

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

我们在使用手机的时候,经常会遇到一个问题:先是卡死,然后跳出该程序无响应,是否关闭的提示(当然有可能是我们手机性能太差=.=)这是因为线程的阻塞引起的,在这里我讲述一下UI线程,一般处理程序会在UI线程中执行耗时操作,这回导致UI线程阻塞,当UI线程阻塞,屏幕会出现卡死,用户体验会变得非常差,当线程阻塞超过5s,android系统可能进行干预,弹出对话框询问是否关闭.那如何解决呢? 解决方案一:创建一个新线程 我在UI视图中创建了一个button和一个textView Button button

Android学习:AsyncTask方案解决UI线程阻塞

post方式能解决UI线程阻塞问题,但是代码的可读性较差. 一:看程序 二:定义AsyncTask private class testTask extends AsyncTask<String, Void, Integer> { protected Integer doInBackground(String... arg0) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace();

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

原文:jQuery同步Ajax带来的UI线程阻塞问题及解决办法 俗话说不作死就不会死,今天作死了一回,写了一个比较二逼的函数,遇到了同步Ajax引起的UI线程阻塞问题,在此记录一下. 事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的原则,我封装了一个名为getData的函数,它接收不同参数,只负责获取数据,然后把数据return.基本的逻辑剥离出来是这样的: function getData1(){ var result; $.ajax({ url : 'p.php'

Android学习:UI线程阻塞

一:看程序 二:现象 程序启动,button1会自动向右滑动三次,但是当点击Button2的时候,button1移动会暂停5秒. 三:线程阻塞: 当一个应用程序启动之后,android系统会为这个应用创建一个主线程.这个线程非常重要,它负责渲染视图,分发事件到响应监听器并执行,对界面进行轮询监听.因此,一般也叫做"UI线程". android系统不会给应用程序的多个元素组件,建立多个线程来执行.一个视图Activity中的多个view组件运行在同一个UI线程中.因此,多个view组件的

Android学习:UI线程阻塞post解决方案

一:看程序 二:post方法 //线程阻塞优化方案1:post方法 v.post(new Runnable() { @Override public void run() { int sum = 10; TextView view = (TextView) v; view.setText("" + sum); } }); 三:后台日志 说明post方法,执行内容放到UI主线程执行.

Javascript之UI线程与性能优化

在浏览器中,Javascript执行与UI更新是发生在同一个进程(浏览器UI线程)中的.UI线程的工作基于一个简单的队列系统,任务会被保存到队列中直到进程空闲时被提取出来执行.所以Javascript的执行会阻塞UI更新;反之,UI更新也会阻塞Javascript的执行.给用户的表现就是浏览器在工作时短暂或长时间失去反应,用户的操作不能及时得到响应.而UI线程的阻塞很多时候是由于我们要在代码里进行长时间的脚本运算,超过了浏览器限制,导致浏览器失去响应,冻结用户界面. 所以,编码时对于耗时较长的运

二、UI线程和界面卡死

上回说到,在Windows窗体程序中,响应Windows消息的线程就被称做Windows窗体程序的UI线程.UI线程还有一个重要的功能是创建和管理窗体和窗体中的各种控件,负责他们的实时刷新,如果UI线程在处理某个消息的时候耗时特别长,那么后续的消息就无法及时响应,看上去的感觉就是“界面卡死”了.此外,为了避免出现线程安全类的问题,UI控件是不能多线程访问的,一个backgroundworker线程直接去刷新控件,这是绝对不允许的,但这种需求又是客观存在的(比方说从数据库中获取数据后刷新到控件中)

UWP开发入门(二十一)——保持Ui线程处于响应状态

GUI的程序有时候会因为等待一个耗时操作完成,导致界面卡死.本篇我们就UWP开发中可能遇到的情况,来讨论如何优化处理. 假设当前存在点击按钮跳转页面的操作,通过按钮打开的新页面,在初始化过程中存在一些耗时的操作. public void OnNavigatedTo(object obj) { var watch = new Stopwatch(); Debug.WriteLine("---------------Start"); watch.Start(); //假设耗时1秒 DoBu

Android中高效的显示图片之二——在非UI线程中处理图片

在“加载大图”文章中提到的BitmapFactory.decode*方法,如果源数据是在磁盘.网络或其它任何不是在内存中的位置,那么它都不应该在UI线程中执行.因为它的加载时间不可预测且依赖于一系列因素(磁盘读写速度.图片大小.CPU频率等).如果在主线程中执行这个操作,一旦它阻塞了主线程,就会导致系统ANR.本节介绍使用AsyncTask在后台处理图片和演示怎么处理并发问题. 一.使用一个AsyncTask AsyncTask类提供一个简易的方法在后台线程中执行一些任务并把结果发布到UI线程.