异步加载之AsyncTask

到底什么是AsyncTask,从字面上理解为异步任务处理,看看文档上是如何介绍的:

点击(此处)折叠或打开

  1. 点击(此处)折叠或打开
  2. AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to
  3. manipulate threads and/or handlers.AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks
  4. should ideally be used for short operations (a few seconds at the most.)If you need to keep threads running for long periods of time, it is highly recommended you use
  5. the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.An asynchronous task is defined by a computation that
  6.  runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps,called
  7.  onPreExecute, doInBackground, onProgressUpdate and onPostExecute.
AsyncTask使适当的和易用的UI线程。这个类可以执行后台操作,并在用户界面上发布结果,而不必处理线程和/或处理程序。AsyncTask的设计是围绕线程和处理器的一个辅助类,并不构成一个通用的线程框架。asynctasks应该用于短作业(最多几秒钟)如果你需要保持线程运行很长一段时间,我们强烈建议您使用不同的java.util.concurrent包如执行API提供的,线程池和futuretask。异步任务被定义为一个在后台线程上运行的运算,其结果是在用户界面上发布的。一个异步任务是由3的泛型类型定义为参数,过程和结果,和4个步骤,称为onpreexecute,doInBackground,onProgressUpdate和onpostexecute。


文档上说的很明白AsyncTask有三个泛型参数,即:

AsyncTask  

Params: 指定传递给异步任务执行时的参数的类型
Progress: 指定异步任务在执行的时候将执行的进度返回给UI线程的参数类型
Result: 指定异步任务执行完后返回给UI线程的结果的类型
看下有哪些步骤:其中doInBackground(Params...)方法是必须要重写的

onPreExecute() :这个方法会在后台任务开始执行之前调用,用于进行一些界面上的初始化操作,比 如显示一个进度条对话框等。

doInBackground(params...) :这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。任务一旦完成就可以通过 return语句来将任务的执行结果返回,如果 AsyncTask的 第三个泛型参数指定的是 Void,就可以不返回任务执行结果。注意,在这个方法中是不 可以进行 UI操作的!如果需要更新 UI元素,比如说反馈当前任务的执行进度,可以调 用 publishProgress(Progress...)方法来完成。

onProgressUpdate(Progress...) :当在后台任务(doInBackground(params...)) 中调用publishProgress(Progress...)方法后,这个方法就会很快被调 用,方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对 UI进行操 作,利用参数中的数值就可以对界面元素进行相应地更新。

onPostExecute(Result):当后台任务执行完毕并通过 return语句进行返回时,这个方法就很快会被调用方法,用于在执行完后台任务后更新UI,显示结果 。

那么如何执行我们的AsyncTask呢?

execute(Params... params)
Executes the task with the specified parameters. 

下面通过一个具体的Demo来简单使用AsyncTask。从服务器上请求数据后显示在TextView中,布局文件很简单:

点击(此处)折叠或打开

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:orientation="vertical"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="match_parent">
  6.     <Button
  7.         android:id="@+id/execute"
  8.         android:layout_width="match_parent"
  9.         android:layout_height="wrap_content"
  10.         android:text="execute"/>
  11.     <ScrollView
  12.         android:layout_width="match_parent"
  13.         android:layout_height="wrap_content">
  14.         <TextView
  15.             android:id="@+id/textview"
  16.             android:layout_width="match_parent"
  17.             android:layout_height="wrap_content"/>
  18.     </ScrollView>
  19. </LinearLayout>
因为要在我们自己的AsyncTask中更新UI,为了方便,使用内部类:

public class MainActivity extends Activity {
    private static final String Address="https://api.heweather.com/x3/weather?cityid=CN101010100"+
"&key=d24f83bc910249758a0f1bc849717c30";
    private Button Request; 
    private TextView textView;  
    private MyAsyncTask myAsync;  
      
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);   
        Request = (Button) findViewById(R.id.execute);  
        textView = (TextView)findViewById(R.id.textview);
        Request.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                myAsync = new MyAsyncTask();  //每次需new一个实例,新建的任务只能执行一次,否则会出现异常 
                myAsync.execute(Address); 
            }  
        });  
       
    }
    private class MyAsyncTask extends AsyncTask {   
        @Override  
        protected void onPreExecute() {
           textView.setText("即将显示数据,请稍等!");  
        }  
          
        //doInBackground方法内部执行后台任务,不可在此方法内修改UI  
		@Override  
        protected StringBuilder doInBackground(String ... params) { 
        	HttpURLConnection connection = null;
        	StringBuilder response = new StringBuilder();
			try{
				URL url = new URL(params[0]);
				connection = (HttpURLConnection)url.openConnection();
				connection.setRequestMethod("GET");
				connection.setConnectTimeout(8000);
			        connection.setReadTimeout(8000);
				InputStream in = connection.getInputStream();
				BufferedReader reader = new BufferedReader(new InputStreamReader(in));
			
				String line;
				while((line = reader.readLine()) != null){
					response.append(line);
				}
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				    if(connection != null){
				    	
					   connection.disconnect();
				}
			}
                 
			return response;
        }  
          
        
        @SuppressWarnings("unused")
		protected void onProgressUpdate() {   //onProgressUpdate用于更新进度信息  

        }  
        @Override  
        protected void onPostExecute(StringBuilder result) {   
            String text = result.toString();
            textView.setText(text);  
           
        }  
         
    }  
} 

上面只是简单的获取数据后,然后在onPostExecute()中更新UI,没有在onProgressUpdate(Progress...)中重写任务进度信息,感兴趣可以简单添加ProgressBar来显示任务执行信息。
如果理解AsyncTask,在Handler中实现上面功能,非常简单了!

public class HttpURLConnectActivity extends Activity implements OnClickListener{
        private static final String Address="https://api.heweather.com/x3/weather?cityid=CN101010100"+"&key=d24f83bc910249758a0f1bc849717c30";
public static final int SHOW_RESPONSE = 0; private Button sendRequest; private TextView responseText; @SuppressLint("HandlerLeak") private Handler handler = new Handler(){ public void handleMessage(Message msg){ switch(msg.what){ case SHOW_RESPONSE: String response1 = (String)msg.obj; responseText.setText(response1); } } }; public void onCreat(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_httpurlconnection); sendRequest =(Button)findViewById(R.id.send_request); responseText =(TextView)findViewById(R.id.request); sendRequest.setOnClickListener(this); } public void onClick(View view){ if(view.getId() == R.id.send_request){ sendRequestWithHttpURLConnection(); } } private void sendRequestWithHttpURLConnection(){ new Thread(new Runnable(){ public void run(){ HttpURLConnection connection = null; try{ URL url = new URL( Address );
connection = (HttpURLConnection)url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(8000); connection.setReadTimeout(8000); InputStream in = connection.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder response = new StringBuilder(); String line; while((line = reader.readLine()) != null){ response.append(line); } Message message = new Message(); message.what = SHOW_RESPONSE; message.obj = response.toString(); handler.sendMessage(message); }catch(Exception e){ e.printStackTrace(); }finally{ if(connection != null){ connection.disconnect(); } } } }).start(); } } 直接给出代码了,关于Handler机制的理解,郭霖大神的<<第一行代码>>中说的很清楚,给出书中部分文字说明:

Android中的异步消息处理主要由四个部分组成,
Message、Handler、MessageQueue和 Looper。下面对这四个部分进行一下简要的介绍。
1. Message Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线 程之间交换数据。
上一小节中我们使用到了 Message的 what字段,除此之外还可以使 用 arg1和 arg2字段来携带一些整型数据,使用 obj字段携带一
个 Object对象。 
2. Handler Handler顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消 息一般是使用 Handler的 sendMessage()方法,而发出的消息经过一系列地辗转处理
后, 最终会传递到 Handler的 handleMessage()方法中。
3. MessageQueue MessageQueue是消息队列的意思,它主要用于存放所有通过 Handler发送的消息。 这部分消息会一直存在于消息
队列中,等待被处理。每个线程中只会有一个MessageQueue 对象。
4. Looper Looper是每个线程中的 MessageQueue的管家,调用 Looper的 loop()方法后,就会 进入到一个无限循环当中,然后每当
发现 MessageQueue中存在一条消息,就会将它取 出,并传递到 Handler的 handleMessage()方法中。每个线程中也只会有一个 
Looper对象。 了解了 Message、Handler、MessageQueue以及 Looper的基本概念后,我们再来对异步 消息处理的整个流程梳理一遍。
首先需要在主线程当中创建一个 Handler 对象,并重写 handleMessage()方法。然后当子线程中需要进行 UI操作时,
就创建一个 Message 对象,并通过 Handler将这条消息发送出去。之后这条消息会被添加到 MessageQueue的队列中
等待 被处理,而 Looper则会一直尝试从 MessageQueue中取出待处理消息,最后分发回 Handler 的 handleMessage()
方法中。由于 Handler是在主线程中创建的,所以此时 handleMessage()方 法中的代码也会在主线程中运行,于是我
们在这里就可以安心地进行 UI操作了。 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29876893/viewspace-2082492/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/29876893/viewspace-2082492/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值