由于Android规定只有UI线程才能更新用户界面和接受用户的按钮及触摸事件,那么就必须保证UI线程不可以被阻塞,从而耗时操作必须要开启一个新的线程来处理!等耗时操作结束以后,必须把最新的数据传给UI线程能处理的地方。

主要有以下四种方法来处理:

1、Handler

Handler用于异步消息处理,在后台线程与UI线程的交互中最常用,Handler自己并不会创建线程,一般Handler用于计划任务和线程间的通信。

Handler处理多线程的原理:

系统启动程序时,会自动为UI线程创建一个消息队列和用于管理这个消息队列的Looper。在创建后台线程时,默认是不会创建Looper和消息队列的。但是可以通过调用Looper.prepare()给后台线程创建Looper和消息队列。

Activity所在的UI线程在创建的时候,就关联了Looper和消息队列(MessageQueue),那么我们又在UI线程里创建了自己的Handler,那么Handler属于UI线程,从而它是可以和UI线程交互的。

UI线程提供消息队列MessageQueueHandler向其中填写MessageUI线程的Looper一直在进行Loop操作,在MessageQueue中读取符合要求的Message给属于它的TargetHandler来处理,最终被从属于UI线程的HandlerhandlMessageMessage msg)方法被调用。

例如:

new TestThread(MainActivity.this).start();

//后台线程类 
    class TestThread extends Thread 
    { 
        Activity activity; 
        public TestThread(Activity activity) { 
             
            this.activity = activity; 
        } 
        @Override 
        public void run() { 
            //下面代码用来演示Handler方法的实现 
            Message msg=new Message(); 
            Bundle bundle=new Bundle(); 
            bundle.putString("tag", "Test Handler"); 
            msg.setData(bundle);             
            new TestHandler(Looper.getMainLooper()).sendMessage(msg); 
                     
            super.run(); 
        } 
         
    } 

//用于线程间通信的Handler 
    class TestHandler extends Handler 
    { 
         
        public TestHandler(Looper looper) { 
            super(looper); 
            // TODO Auto-generated constructor stub 
        } 
 

//handleMessage里面修改主UI
        @Override 
        public void handleMessage(Message msg) { 
            // TODO Auto-generated method stub 
            System.out.println("123"); 
            txView.setText((String)msg.getData().get("tag")); 
            super.handleMessage(msg); 
        } 
         
    } 

2Activity.runOnUIThread(Runnable)

new TestThread(MainActivity.this).start();

//后台线程类 

class TestThread extends Thread 
    { 
        Activity activity; 
        public TestThread(Activity activity) { 
             
            this.activity = activity; 
        } 
        @Override 
        public void run() { 
             
            //下面代码用来演示Activity.runOnUIThread(Runnable)方法的实现 
            activity.runOnUiThread(new Runnable() {              
                @Override 
                public void run() { 
                    // TODO Auto-generated method stub 
                    txView.setText("Test runOnUIThread"); 
                } 
            }); 

}

}
3View.post(Runnable)View.postDelay(Runnable,long)

new TestThread(MainActivity.this).start();

//后台线程类 
class TestThread extends Thread 
    { 
        Activity activity; 
        public TestThread(Activity activity) { 
             
            this.activity = activity; 
        } 
        @Override 
        public void run() { 
             
            //下面代码用来演示View.post(Runnable)方法的实现 
            txView.post(new Runnable() { 
                 
                @Override 
                public void run() { 
                    // TODO Auto-generated method stub 
                    txView.setText("Test View.post(Runnable)"); 
                } 
            }); 
             
            //下面代码用来演示View.postDelay(Runnable,long)方法的实现 
            txView.postDelayed(new Runnable() { 
                 
                @Override 
                public void run() { 
                    // TODO Auto-generated method stub 
                    txView.setText("Test View.postDelay(Runnable,long)"); 
                } 
            }, 1000); 

}

}
4AsyncTask<Params,Progress,Result>

Params,Progress,Result都是数据类型,

Params要处理的数据的类型

Progress处理进度的类型

Result处理后返回的结果

 

它是一个异步处理的简单方法!

方法的执行顺序:

1

onPreExecute() --UI线程中执行,作一些初始化操作

 

2

doInBackground(Params... params) --在子线程中执行,进行耗时的后台处理,在该方法中可以调用publishProgress(Progress progress) 进行进度处理

 

3

onProgressUpdate(Progress progress) --UI线程中执行,进行进度实时处理

 

4onPostExecute(Result result) --UI线程中执行, 在doInBackground(Params ... params)返回后调用

 

5

onCancelled() --UI线程中执行,在AsyncTask实例调用cancle(true)方法后执行,作一些清理操作

 

几点注意:

AsyncTask必须在UI线程中创建,

asyncTask.execute(Params... params) ;UI线程中执行,且只能执行一次

要想再次调用execute(Params... params),必须重新创建AsyncTask对象

源码示例:

//创建一个用于展示AsyncTask实现交互的TestAsyncTask 
    new TestAsyncTask().execute("Test"," AsyncTask");

class TestAsyncTask extends AsyncTask<String, Integer, String> 

    { 

        //TestAsyncTask被后台线程执行后,被UI线程被调用,一般用于初始化界面控件,如进度条 

        @Override 

        protected void onPreExecute() { 

            // TODO Auto-generated method stub 

            super.onPreExecute(); 

        } 

 

        //PreExcute执行后被启动AysncTask的后台线程调用,将结果返回给UI线程 

        @Override 

        protected String doInBackground(String... params) { 

            // TODO Auto-generated method stub 

            StringBuffer sb=new StringBuffer(); 

            for (String string : params) { 

                sb.append(string); 

            } 

            return sb.toString(); 

        } 

         

    }        

 //doInBackground执行完后由UI线程调用,用于更新界面操作 

        @Override 

        protected void onPostExecute(String result) { 

            // TODO Auto-generated method stub 

            txView.setText(result); 

            super.onPostExecute(result); 

        }