• 10 UI线程阻塞及其优化


    1button1移动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 threadUI 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、用解决方案1view.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、用解决方案2AsyncTask:(最佳解决方案)

    异步:此方法写法与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);
            } 
        }
        
    
    }

    运行结果:

  • 相关阅读:
    每日日报
    每日日报
    JAVA日报
    JAVA日报
    JAVA日报
    JAVA日报
    NavigationDuplicated {_name: "NavigationDuplicated", name: "NavigationDuplicated"}
    2020.11.07
    2020.11.05
    2020.11.09
  • 原文地址:https://www.cnblogs.com/cxm-weiniss/p/7204762.html
Copyright © 2020-2023  润新知