使用AsyncTask异步更新UI界面(加载网络图片)
2015-09-22 10:19
549 查看
写这个博客时抽抽了,顺便又用了一些WebView的东西,更多webview参见这里
1.简单介绍下AsyncTask
AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.比Handler更轻量级,但是在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.代码量上,如果只开一个后台进程AsyncTask是绝对首选,因为handler处理结构相对复杂。
2.使用
要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个doInBackground)。
参考:http://www.cnblogs.com/devinzhang/archive/2012/02/13/2350070.html
AsyncTask定义了三种泛型类型 Params,Progress和Result。
Params 启动任务执行的输入参数,比如HTTP请求的URL。
Progress 后台任务执行的百分比, 比如Integer。
Result 后台执行任务最终返回的结果,比如String。
使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:
doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回
有必要的话你还得重写以下这三个方法,但不是必须的:
onProgressUpdate(Progress…) 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
onCancelled() 用户调用取消时,要做的操作
总结一句话:
在主线程中调用YouAsyncTask.execute("你的参数"),doInBackground(...)里面的参数就是你传的参数集,你可以在这里处理耗时操作,它会返回一个结果result给onPostExecute(...)在这里处理结果,如果你在doInBackground(...)中调用了publishProgress(progressNumber)方法,那么进度的显示在onProgressUpdate(...)中,里面的参数就是progressNumber。
使用AsyncTask类,以下是几条必须遵守的准则:
Task的实例必须在UI thread中创建;
execute方法必须在UI thread中调用;
不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
该task只能被执行一次,否则多次调用时将会出现异常;
3.看个栗子
建立在上一个博客项目基础上,创建了新的布局处理。
XMl:activity_async_task.xml
AsyncTaskActivity.java(该文件弃用,因为后来优化遇到了些问题,作为对比故保留,详见第二个文件)
vvvvvvvv22222222222222222222222222↓
里面有用到一个缩放比的工具类:在这里
☆的说明参看博客:/article/1904195.html
最后别忘了添加网络访问权限
不了解HttpClient用法的参见这篇博客:http://blog.csdn.net/bhq2010/article/details/9210007
我把manifest也贴出来吧:
至此关于AsyncTask的使用就是这么简单。
栗子源码下载:点我下载
—— lovey hy.
1.简单介绍下AsyncTask
AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.比Handler更轻量级,但是在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.代码量上,如果只开一个后台进程AsyncTask是绝对首选,因为handler处理结构相对复杂。
2.使用
要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个doInBackground)。
参考:http://www.cnblogs.com/devinzhang/archive/2012/02/13/2350070.html
AsyncTask定义了三种泛型类型 Params,Progress和Result。
Params 启动任务执行的输入参数,比如HTTP请求的URL。
Progress 后台任务执行的百分比, 比如Integer。
Result 后台执行任务最终返回的结果,比如String。
使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:
doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回
有必要的话你还得重写以下这三个方法,但不是必须的:
onProgressUpdate(Progress…) 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
onCancelled() 用户调用取消时,要做的操作
总结一句话:
在主线程中调用YouAsyncTask.execute("你的参数"),doInBackground(...)里面的参数就是你传的参数集,你可以在这里处理耗时操作,它会返回一个结果result给onPostExecute(...)在这里处理结果,如果你在doInBackground(...)中调用了publishProgress(progressNumber)方法,那么进度的显示在onProgressUpdate(...)中,里面的参数就是progressNumber。
使用AsyncTask类,以下是几条必须遵守的准则:
Task的实例必须在UI thread中创建;
execute方法必须在UI thread中调用;
不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
该task只能被执行一次,否则多次调用时将会出现异常;
3.看个栗子
建立在上一个博客项目基础上,创建了新的布局处理。
XMl:activity_async_task.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/download" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:padding="10dp" android:text="download" /> <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_below="@id/download" android:layout_marginTop="10dp" android:scaleType="centerCrop"/> <SeekBar android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_below="@id/image" android:layout_margin="5dp" android:max="100" android:progress="0" android:id="@+id/seekbar"/> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/seekbar"/> </RelativeLayout>
AsyncTaskActivity.java(该文件弃用,因为后来优化遇到了些问题,作为对比故保留,详见第二个文件)
package com.lzy.exploremessagedemo; import java.io.IOException; import java.io.InputStream; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import android.annotation.SuppressLint; 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.view.View.OnClickListener; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.Button; import android.widget.ImageView; import android.widget.SeekBar; import android.widget.Toast; public class AsyncTaskActivity extends Activity { private Button downloadButton; private ImageView mImageView; private ProgressDialog progressDialog; private SeekBar seekBar; private WebView webView; private final String url = "http://b.hiphotos.baidu.com/image/h%3D300/sign=1b921b860d24ab18ff16e" + "73705fbe69a/86d6277f9e2f070861ccd4a0ed24b899a801f241.jpg"; @SuppressLint("SetJavaScriptEnabled") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_async_task); progressDialog = new ProgressDialog(this); mImageView = (ImageView) findViewById(R.id.image); seekBar = (SeekBar) findViewById(R.id.seekbar); webView = (WebView) findViewById(R.id.webview); WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); settings.setBuiltInZoomControls(true); settings.setDisplayZoomControls(true); settings.setSupportZoom(true); downloadButton = (Button) findViewById(R.id.download); downloadButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { new MyAsyncTask().execute(url);//异步加载网络图片 webView.loadUrl(url);//使用webview加载网络图片 } }); } class MyAsyncTask extends AsyncTask<String, Integer, Bitmap>{//参数,进度,结果 @Override protected void onPreExecute() { progressDialog.setMessage("请稍后..."); progressDialog.show(); } @Override protected Bitmap doInBackground(String... prarm) { String url = prarm[0]; Bitmap bitmap = null; HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); try { HttpResponse httpResponse = httpClient.execute(httpGet); if (HttpStatus.SC_OK == httpResponse.getStatusLine().getStatusCode()) { HttpEntity entity = httpResponse.getEntity(); InputStream in = entity.getContent(); bitmap = BitmapFactory.decodeStream(in); publishProgress(100);//进度显示,这里作为一个知识点,结果显示回调在onProgressUpdate(Integer... values)方法中 } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { httpClient.getConnectionManager().shutdown(); } return bitmap; } @Override protected void onProgressUpdate(Integer... values) { seekBar.setProgress(values[0]); } @Override protected void onPostExecute(Bitmap result) { progressDialog.dismiss(); mImageView.setImageBitmap(result); Toast.makeText(getApplicationContext(), "下载成功!", Toast.LENGTH_SHORT).show(); } } }
vvvvvvvv22222222222222222222222222↓
package com.lzy.exploremessagedemo; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import android.annotation.SuppressLint; 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.view.View.OnClickListener; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.Button; import android.widget.ImageView; import android.widget.SeekBar; import android.widget.Toast; public class AsyncTaskActivity extends Activity { private Button downloadButton; private ImageView mImageView; private ProgressDialog progressDialog; private SeekBar seekBar; private WebView webView; private final String url = "http://b.hiphotos.baidu.com/image/h%3D300/sign=1b921b860d24ab18ff16e" + "73705fbe69a/86d6277f9e2f070861ccd4a0ed24b899a801f241.jpg"; @SuppressLint("SetJavaScriptEnabled") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_async_task); progressDialog = new ProgressDialog(this); mImageView = (ImageView) findViewById(R.id.image); seekBar = (SeekBar) findViewById(R.id.seekbar); webView = (WebView) findViewById(R.id.webview); WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); settings.setBuiltInZoomControls(true); settings.setDisplayZoomControls(true); settings.setSupportZoom(true); downloadButton = (Button) findViewById(R.id.download); downloadButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { new MyAsyncTask().execute(url); webView.loadUrl(url); } }); } class MyAsyncTask extends AsyncTask<String, Integer, Bitmap>{//参数,进度,结果 @Override protected void onPreExecute() { progressDialog.setMessage("请稍后"); progressDialog.show(); } @SuppressWarnings("unused") @Override protected Bitmap doInBackground(String... prarm) { String url = prarm[0]; Bitmap bitmap = null; InputStream in = null; HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); try { HttpResponse httpResponse = httpClient.execute(httpGet); if (HttpStatus.SC_OK == httpResponse.getStatusLine().getStatusCode()) { HttpEntity entity = httpResponse.getEntity(); in = entity.getContent(); long total = entity.getContentLength(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; int count = 0; int length = -1; while ((length = in.read(buf)) != -1) { baos.write(buf, 0, length); count += length; //调用publishProgress公布进度,最后onProgressUpdate方法将被执行 publishProgress((int) ((count / (float) total) * 100)); //为了演示进度,休眠100毫秒 Thread.sleep(100); } /** * @time 2015-9-22 - 下午1:48:59 * @bug 这是android 1.6的一个bug,解决方案如下 * */ //bitmap = BitmapFactory.decodeStream(in);//不清楚为什么这样写获取不到图片,改用如下方式就能了,如果不为了演示进度条的功能,将while注掉,然后使用此方法,却能显示图片?????? //bitmap = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.toByteArray().length); /** * 最终解决办法 * */ if (in == null) { bitmap = BitmapFactory.decodeStream(in); }else { //为了防止加载大图片OOM 采用BitmapFactory.Options进行缩略图处理 BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true;//不返回实际的Bitmap options.inSampleSize = Util.computeSampleSize(options, -1, 128 * 128); //为什么加上options参数获取的Bitmap就为null呢???????????? 心累。。。。。 /** * @time 2015-9-22 - 下午3:03:32 * @bug 这是因为options.inJustDecodeBounds = true后不会创建Bitmap空间只作为暂存,最后 * 还要设置回来显示Bitmap * */ options.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.toByteArray().length, options); } return bitmap; } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); }finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } httpClient.getConnectionManager().shutdown(); } return null; } @Override protected void onProgressUpdate(Integer... values) { seekBar.setProgress(values[0]); } @Override protected void onPostExecute(Bitmap result) { progressDialog.dismiss(); /** * 尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图, * 因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。 ☆ * */ mImageView.setImageBitmap(result); Toast.makeText(getApplicationContext(), "下载成功!", Toast.LENGTH_SHORT).show(); } } }
里面有用到一个缩放比的工具类:在这里
☆的说明参看博客:/article/1904195.html
最后别忘了添加网络访问权限
<uses-permission android:name="android.permission.INTERNET"/>
不了解HttpClient用法的参见这篇博客:http://blog.csdn.net/bhq2010/article/details/9210007
我把manifest也贴出来吧:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.lzy.exploremessagedemo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.Holo.Light" > <activity android:name=".AsyncTaskActivity" <!-- 换成上一篇博文的主文件".MainActivity"就可以启动上一个项目了 --> android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
至此关于AsyncTask的使用就是这么简单。
栗子源码下载:点我下载
—— lovey hy.
相关文章推荐
- 终于明白#!bin/sh是什么意思了 (2009-10-06 21:58:47) http://blog.sina.com.cn/s/blog_4d32d0b40100fngc.html
- 计算机网络面试常考
- win7 VMware CentOS桥接(bridge)模式网络配置
- win7 VMware CentOS桥接(bridge)模式网络配置
- TCP segment of a reassembled PDU
- HTTP Request GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE Methods
- 【TCP】TCP连接建立过程的三次握手
- iOS 网络编程基础
- NSURLSession使用说明及后台工作流程分析
- HTTP协议:缓存
- okhttp使用
- 接口测试及httpclient深入
- HttpClient 通过域名访问请求接口出现java.net.UnknownHostException解决方法
- HttpClient 通过域名访问请求接口出现java.net.UnknownHostException解决方法
- Linux网络IO模型
- 关于Linux的进程和线程 http://kenby.iteye.com/blog/1014039
- 网络编程问题解决方案:查看进程占用了哪个端口号
- 打造安全的App!iOS安全系列之 HTTPS 进阶
- 虚拟机桥接网络连接方式
- 2015北京网络赛 G Boxes BFS+打表