天天看点

android 界面刷新 post send

一,问题引入

       异常: Only the original thread that created a view hierarchy can touch its views的解决方案   

       为什么会有这种异常产生呢?

      当每个应用程序apk第一次启动时,Android会同时启动一个对应的主线程(Main Thread),

      主线程负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,

      并把相关的事件分发到对应的组件进行处理,所以主线程通常又被叫做UI线程。

      但是在开发Android应用时必须遵守单线程模型的原则: 

      Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行,如果在非UI线程中直接操作UI线程,

      会抛出android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that 

      created a view hierarchy can touch its views,这与普通的java程序不同。

       由于UI线程负责事件的监听和绘图,因此,必须保证UI线程能够随时响应用户的需求,

       UI线程里的操作应该向中断事件那样短小,费时的操作(如网络连接)需要另开线程,

       否则,如果UI线程超过5s没有响应用户请求,会弹出对话框提醒用户终止应用程序(ANP)。

       如果在新开的线程中需要对UI进行设定,就可能违反单线程模型,

       因此android采用一种的Message Queue机制保证线程间通信。

       Message Queue是一个消息队列,用来存放通过Handler发送的消息。

       Android在第一启动程序时会默认会为UI thread创建一个关联的消息队列,

      可以通过Looper.myQueue()得到当前线程的消息队列,用来管理程序的一些上层组件,

      activities,broadcast receivers 等,你可以在自己的子线程中创建Handler与UI thread通讯。

      Handler会向message queue通过两种方法发送消息:send或post。

      这两种消息都会插在message queue队尾并按先进先出执行,

      但通过这两种方法发送的消息执行的方式略有不同:

      1)通过send发送的是一个message对象, 会被handler的 handleMessage()函数处理;

      2)而通过post方法发送的是一个runnable对象,则会自己执行。

      每个带图形界面的应用启动后,都会创建一个主线程,可称之为UI线程。

      这个线程自动就会创建一个message queue,来自于系统的消息都会投放到这个message queue里面,

      并按先进先出的顺序处理。

      UI线程图形界面中的view可通过post方法向GUI线程的message queue投递一个runnable。

     对于除UI线程以外的其他线程,创建时缺省并没有message queue,

     而对于UI线程,则可以直接(比如在onCreate)创建一个handler并重载handleMessage,

     省去创建message queue的过程。

二,解决方案一

final Handler handler = new Handler(){     

            @Override  

        public void handleMessage(Message msg) {     

            if(msg.what == 0)//成功     

            {  

                Log.d(TAG, "**********************start****************************");  

                playVideo(strVideoPath);//包含更新界面的方法  

                Log.d(TAG, "***********************end*****************************");  

            }  

        }   

    };     

    new Thread()   

        {  

        public void run()  

        {     

                   // handler.post(runnableUi);     

                    try{  

                         Log.d(TAG, "######################start###############################");  

                         handler.sendEmptyMessage(0);//UI线程外想更新UI线程  

                         Log.d(TAG, "######################end###############################");  

                    }  

               catch(Exception e)  

                   {  

                       Log.d(TAG, "***************************"+e.toString());  

                   }  

         }  

       }.start();  

<strong><span style="font-size:18px;">三,解决方案二</span></strong>  

<pre class="html" name="code">Runnable   runnableUi=new  Runnable(){    

        @Override    

        public void run() {    

            //更新界面    

            textView.setText("the Content is:"+content);    

        }    

    };    

  new Thread(){    

                public void run(){      

                    content=df.downLoadFiles();         

                    handler.post(runnableUi);     

                    }                       

            }.start();  

四,特别注意,引入函数包得时候,不要引入错误的包

             import android.os.Handler; //这是正确的包

             import java.util.logging.Handler;//不是这个包,而是上一个

继续阅读