android 异步方式实现数据加载
来源:互联网 发布:mv 文件夹 linux 编辑:程序博客网 时间:2024/05/13 23:54
使用AsyncTask实现异步处理
由于主线程(也可叫UI线程)负责处理用户输入事件(点击按钮、触摸屏幕、按键等),如果主线程被阻塞,应用就会报ANR错误。为了不阻塞主线程,我们需要在子线程中处理耗时的操作,在处理耗时操作的过程中,子线程可能需要更新UI控件的显示,由于UI控件的更新重绘是由主线程负责的,所以子线程需要通过Handler发送消息给主线程的消息队列,由运行在主线程的消息处理代码接收消息后更新UI控件的显示。
采用线程+Handler实现异步处理时,当每次执行耗时操作都创建一条新线程进行处理,性能开销会比较大。另外,如果耗时操作执行的时间比较长,就有可能同时运行着许多线程,系统将不堪重负。为了提高性能,我们可以使用AsynTask实现异步处理,事实上其内部也是采用线程+Handler来实现异步处理的,只不过是其内部使用了线程池技术,有效的降低了线程创建数量及限定了同时运行的线程数。
private final class AsyncImageTask extends AsyncTask<String, Integer, String>{
protectedvoid onPreExecute(){ //运行在UI线程
}
protectedStringdoInBackground(String...params) {//在子线程中执行
return“itcast”;
}
protectedvoid onPostExecute(String result) {//运行在UI线程
}
protectedvoid onProgressUpdate(Integer… values) {//运行在UI线程
}
}
AsyncTask<String, Integer, String>中定义的三个泛型参数分别用作了doInBackground、onProgressUpdate的输入方法类型,第三个参数用作了doInBackground的返回参数类型和onPostExecute的输入参数类型。
AsyncTask定义了三种泛型类型Params,Progress和Result。
- Params 启动任务执行的输入参数,比如HTTP请求的URL。
- Progress 后台任务执行的百分比。
- Result 后台执行任务最终返回的结果,比如String。
使用AsyncTask异步加载数据最少要重写以下这两个方法:
- doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
- onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回
有必要的话还得重写以下这三个方法,但不是必须的:
- onProgressUpdate(Progress…) 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
- onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
- onCancelled()用户调用取消时,要做的操作
使用AsyncTask类,以下是几条必须遵守的准则:
- Task的实例必须在UI thread中创建;
- execute方法必须在UI thread中调用;
- 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
- 该task只能被执行一次,否则多次调用时将会出现异常;
1、Contact.java创建数据对象类
- package cn.org.domain;
- public class Contact {
- public int id;
- public String name;
- public String image;
- public Contact(int id, String name, String image) {
- this.id = id;
- this.name = name;
- this.image = image;
- }
- public Contact(){}
- }
2.这里我们首先需要准备好数据,是通过解析web service中的xml数据,数据是通过MD5进行加密的ContactService.java
- package cn.itcast.service;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.InputStream;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.util.ArrayList;
- import java.util.List;
- import org.xmlpull.v1.XmlPullParser;
- import android.net.Uri;
- import android.util.Xml;
- import cn.org.domain.Contact;
- import cn.org.utils.MD5;
- public class ContactService {
- /**
- * 获取联系人
- * @return
- */
- public static List<Contact> getContacts() throws Exception{
- String path = "http://192.168.1.100:8080/web/list.xml";
- HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
- conn.setConnectTimeout(5000);
- conn.setRequestMethod("GET");
- if(conn.getResponseCode() == 200){
- return parseXML(conn.getInputStream());
- }
- return null;
- }
- private static List<Contact> parseXML(InputStream xml) throws Exception{
- List<Contact> contacts = new ArrayList<Contact>();
- Contact contact = null;
- XmlPullParser pullParser = Xml.newPullParser();
- pullParser.setInput(xml, "UTF-8");
- int event = pullParser.getEventType();
- while(event != XmlPullParser.END_DOCUMENT){
- switch (event) {
- case XmlPullParser.START_TAG:
- if("contact".equals(pullParser.getName())){
- contact = new Contact();
- contact.id = new Integer(pullParser.getAttributeValue(0));
- }else if("name".equals(pullParser.getName())){
- contact.name = pullParser.nextText();
- }else if("image".equals(pullParser.getName())){
- contact.image = pullParser.getAttributeValue(0);
- }
- break;
- case XmlPullParser.END_TAG:
- if("contact".equals(pullParser.getName())){
- contacts.add(contact);
- contact = null;
- }
- break;
- }
- event = pullParser.next();
- }
- return contacts;
- }
- /**
- * 获取网络图片,如果图片存在于缓存中,就返回该图片,否则从网络中加载该图片并缓存起来
- * @param path 图片路径
- * @return
- */
- public static Uri getImage(String path, File cacheDir) throws Exception{// path -> MD5 ->32字符串.jpg
- File localFile = new File(cacheDir, MD5.getMD5(path)+ path.substring(path.lastIndexOf(".")));
- if(localFile.exists()){
- return Uri.fromFile(localFile);
- }else{
- HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
- conn.setConnectTimeout(5000);
- conn.setRequestMethod("GET");
- if(conn.getResponseCode() == 200){
- FileOutputStream outStream = new FileOutputStream(localFile);
- InputStream inputStream = conn.getInputStream();
- byte[] buffer = new byte[1024];
- int len = 0;
- while( (len = inputStream.read(buffer)) != -1){
- outStream.write(buffer, 0, len);
- }
- inputStream.close();
- outStream.close();
- return Uri.fromFile(localFile);
- }
- }
- return null;
- }
- }
- package cn.org.utils;
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
- public class MD5 {
- public static String getMD5(String content) {
- try {
- MessageDigest digest = MessageDigest.getInstance("MD5");
- digest.update(content.getBytes());
- return getHashString(digest);
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- return null;
- }
- private static String getHashString(MessageDigest digest) {
- StringBuilder builder = new StringBuilder();
- for (byte b : digest.digest()) {
- builder.append(Integer.toHexString((b >> 4) & 0xf));
- builder.append(Integer.toHexString(b & 0xf));
- }
- return builder.toString();
- }
- }
3.ContactAdapter.java 我们来适配绑定数据,这里我们通过异步方式实现
- package cn.org.adapter;
- import java.io.File;
- import java.util.List;
- import cn.org.asyncload.R;
- import cn.org.domain.Contact;
- import cn.org.service.ContactService;
- import android.content.Context;
- import android.net.Uri;
- import android.os.AsyncTask;
- import android.os.Handler;
- import android.os.Message;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.ImageView;
- import android.widget.TextView;
- public class ContactAdapter extends BaseAdapter {
- private List<Contact> data;
- private int listviewItem;
- private File cache;
- LayoutInflater layoutInflater;
- public ContactAdapter(Context context, List<Contact> data, int listviewItem, File cache) {
- this.data = data;
- this.listviewItem = listviewItem;
- this.cache = cache;
- layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
- /**
- * 得到数据的总数
- */
- public int getCount() {
- return data.size();
- }
- /**
- * 根据数据索引得到集合所对应的数据
- */
- public Object getItem(int position) {
- return data.get(position);
- }
- public long getItemId(int position) {
- return position;
- }
- public View getView(int position, View convertView, ViewGroup parent) {
- ImageView imageView = null;
- TextView textView = null;
- if(convertView == null){
- convertView = layoutInflater.inflate(listviewItem, null);
- imageView = (ImageView) convertView.findViewById(R.id.imageView);
- textView = (TextView) convertView.findViewById(R.id.textView);
- convertView.setTag(new DataWrapper(imageView, textView));
- }else{
- DataWrapper dataWrapper = (DataWrapper) convertView.getTag();
- imageView = dataWrapper.imageView;
- textView = dataWrapper.textView;
- }
- Contact contact = data.get(position);
- textView.setText(contact.name);
- asyncImageLoad(imageView, contact.image);
- return convertView;
- }
- private void asyncImageLoad(ImageView imageView, String path) {
- AsyncImageTask asyncImageTask = new AsyncImageTask(imageView);
- asyncImageTask.execute(path);
- }
- private final class AsyncImageTask extends AsyncTask<String, Integer, Uri>{
- private ImageView imageView;
- public AsyncImageTask(ImageView imageView) {
- this.imageView = imageView;
- }
- protected Uri doInBackground(String... params) {//子线程中执行的
- try {
- return ContactService.getImage(params[0], cache);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- protected void onPostExecute(Uri result) {//运行在主线程
- if(result!=null && imageView!= null)
- imageView.setImageURI(result);
- }
- }
- private final class DataWrapper{
- public ImageView imageView;
- public TextView textView;
- public DataWrapper(ImageView imageView, TextView textView) {
- this.imageView = imageView;
- this.textView = textView;
- }
- }
- }
- package cn.org.asyncload;
- import java.io.File;
- import java.util.List;
- import cn.org.adapter.ContactAdapter;
- import cn.org.domain.Contact;
- import cn.org.service.ContactService;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Environment;
- import android.os.Handler;
- import android.os.Message;
- import android.widget.ListView;
- public class MainActivity extends Activity {
- ListView listView;
- File cache;
- Handler handler = new Handler(){
- public void handleMessage(Message msg) {
- listView.setAdapter(new ContactAdapter(MainActivity.this, (List<Contact>)msg.obj,
- R.layout.listview_item, cache));
- }
- };
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- listView = (ListView) this.findViewById(R.id.listView);
- cache = new File(Environment.getExternalStorageDirectory(), "cache");
- if(!cache.exists()) cache.mkdirs();
- new Thread(new Runnable() {
- public void run() {
- try {
- List<Contact> data = ContactService.getContacts();
- handler.sendMessage(handler.obtainMessage(22, data));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }).start();
- }
- @Override
- protected void onDestroy() {
- for(File file : cache.listFiles()){
- file.delete();
- }
- cache.delete();
- super.onDestroy();
- }
- }
5.listview_item.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal" >
- <ImageView
- android:layout_width="120dp"
- android:layout_height="120dp"
- android:id="@+id/imageView"
- />
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textSize="18sp"
- android:textColor="#FFFFFF"
- android:id="@+id/textView"
- />
- </LinearLayout>
main.xml<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/listView"/>
</LinearLayout>
- android 异步方式实现数据加载
- android 异步方式实现数据加载
- 异步方式实现数据加载
- android多种方式实现异步加载图片
- android异步任务加载数据界面实现
- Android Loader机制,实现异步加载数据
- Android实现异步加载
- 【Android】使用LoaderManager管理Loader实现异步动态加载数据
- AndroidのLoaderManager管理Loader实现异步动态加载数据
- Android 异步加载数据 AsyncTask
- Android中异步加载数据
- Android异步加载数据---Loader
- Android Loader 异步加载数据
- Android异步加载数据--Loader
- Loaders异步加载数据的方式
- Android 实现异步加载图片
- android 画廊实现异步加载
- 【异步加载】Android 网络数据异步加载解决方案
- SparseArray源码分析
- 详述mysql的聚合查询
- Android中ListView异步加载数据
- install k2pdfopt in MAC OSX
- java int与integer的区别
- android 异步方式实现数据加载
- Hibernate基础知识(二)
- bootstrap 超链接变按钮
- 广义表的实现(c++实现)
- 资料
- android.content.res.Resources$NotFoundException
- Oracle怎么实现分页
- hdu 1058 Humble Numbers 丑数
- 查询某个文件夹下包含某字符的文件和所在行