android的线程是一个很重要的知识点!对用户的操作体验至关重要。
一.什么是线程呢??
给个通俗易懂的一个解释吧!进程好比是一个游泳池,在游泳池当中有很多的水管,每一个水管就相当于是一个线程。而其中有一根主要的水管,其他一些小的水管是给主水管提供辅助帮助,来完成对
泳池进水,出水的任务的。在android线程当中有一个UI线程(主线程),我们自己可以创建一些子线程来帮助主线程进行UI更新等操作。
二.为什么要创建线程呢?
(1)是为了提高用户的操作体验避免产生ANR现象
如果所有的操作都放在一个主线程当中,那只有执行完这一步才能执行下一步操作,如果当前操作很耗时(网络等原因),那应用就会一直"卡"在这一步操作当中,用户只有一直等待。等待时间过长
给用户的体验月糟糕,应用的效益就会越低,以至于到最后没有人会用了。
(2)对于网络耗时操作的异步处理
主线程当中的事件处理不能太耗时,否则后续事件无法再5秒内得到响应,就会弹出ANR对话框。
通常在主线程当中会执行如下一些方法:
a.Activity的生命周期方法, OnCreate(),OnStart(), OnResume()等
b.事件处理方法,例如onClick()、onItemClick()等
通常Android基类中以on开头的方法是在Main线程被回调的
对于网络耗时操作就要开辟新的线程来进行处理,并与主线程进行交互。让用户不用等待结果的情况下,可以进行进行操作(如发送图片给服务器用户只管发送,什么时候服务器能接收到就是网络问题了)
三.子线程与主线程的通讯
(1)android提供了一个辅助类AsyncTask。可以将完成一些耗时的事件,并将事件处理后的结果返回给主线程。但AsyncTask只适合创建单一的线程,创建多线程会比较复杂而且会产生很多重复代码。
下面就对AsyncTask做个简要的讲解:
API是这样解释AsyncTask:This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers
意思是:这个类允许执行一些后台操作并将结果返回给UI线程而不用去创建线程和handler
AsyncTsk下载网络图片:
package com.example.thread; import org.apache.http.HttpEntity; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.DefaultClientConnection; import org.apache.http.util.EntityUtils; import android.app.Activity; import android.app.ProgressDialog; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; public class MainActivity extends Activity { private ImageView image; private ProgressDialog dialog; private Button button; private String imageUrl = "http://img2.3lian.com/img2009/08/3lian14/173.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); image = (ImageView) findViewById(R.id.imageID); button = (Button) findViewById(R.id.button1); dialog = new ProgressDialog(MainActivity.this); dialog.setTitle("图片下载中"); dialog.setMessage("请稍后"); button.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { new MyAsyncTask().execute(imageUrl); } }); } /** * 这里的String参数对应AsyncTask中的第一个参数 这里的Boolean返回值对应AsyncTask的第三个参数 * 该方法并不运行在UI线程当中,主要用于异步操作,所有在该方法中不能对UI当中的空间进行设置和修改 * 但是可以调用publishProgress方法触发onProgressUpdate对UI进行操作 * */ class MyAsyncTask extends AsyncTask<String, Void, Bitmap> { /** * 完成耗时操作,注意这里不能直接操作UI */ @Override protected Bitmap doInBackground(String... params) { HttpClient httpClient = new DefaultHttpClient(); Bitmap bitmap = null; HttpGet httpGet = new HttpGet(params[0]); System.out.println(params[0]); try { HttpResponse response = httpClient.execute(httpGet); System.out.println(response.getStatusLine().getStatusCode()); if (response.getStatusLine().getStatusCode() == 200) { HttpEntity entity = response.getEntity(); // 将图片装换成字节流 byte[] data = EntityUtils.toByteArray(entity); bitmap = BitmapFactory .decodeByteArray(data, 0, data.length); } } catch (Exception e) { } return bitmap; } /** * 耗时操作执行前所执行的 */ @Override protected void onPreExecute() { super.onPreExecute(); dialog.show(); } /** * 耗时操作执行后所执行的,主要执行更新UI的操作 */ @Override protected void onPostExecute(Bitmap result) { super.onPostExecute(result); dialog.dismiss(); // 进行UI更新 image.setImageBitmap(result); } } }
要注意是否打开了网络权限!!!
运行效果:
接下来就开始学习handler的多线程