为什么要异步加载:

为了用户体验,避免卡顿

Android系统要求使用异步加载,耗时操作会阻塞UI线程

异步加载的常用的方式:

多线程/线程池

AsyncTask

以下以加载网络图片为示例

在主类之外声明一个单独的MyBean类:

class MyBean{public String MyIconUrl;public String MyTitle;public String MyContent;
} 

和一个MyAdapter类:

public class MyAdapter extends BaseAdapter{private List<MyBean> mList;private LayoutInflater mInflater;public MyAdapter(Context context, List<MyBean> data){mList = data;mInflater = LayoutInflater.from(context);}public int getCount(){return mList.size();}public Object getItem(int position){return mList.get(position);}public long getItemId(int position){return position;}public View getView(int position, View convertView, ViewGroup parent){ViewHolder viewHolder = null;if(convertView == null){viewHolder = new ViewHolder();convertView = mInflater.inflate(R.layout.item_layout, null);viewHolder.ivIcon = (ImageView)convertView.findViewById(R.id.iv_icon);viewHolder.tvTitle = (TextView)convertView.findViewById(R.id.tv_title);viewHolder.tvContent = (TextView)convertView.findViewById(R.id.tv_content);convertView.setTag(viewHolder);}else{viewHolder = (ViewHolder)convertView.getTag();}viewHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);//这是使用默认的ic_launcher作为图标
     //-----------------下述是调用异步加载图片的内容作为图标
     new ImageLoader().showImageByThread(viewHolder.ivIcon, mList.get(position).myIconUrl);
     //-----------------viewHolder.tvTitle.setText(mList.get(position).MyTitle);viewHolder.tvContent.setText(mList.get(position).MyContent);return convertView;}class ViewHolder{public TextView tvTitle, tvContent;public ImageView ivIcon;}
}

接下来是主类中的方法:

private ListView mListView;
private static String URL = "http://www.xxxxxxxxx.com/xxx/xxx/xxx";protected void OnCreate(Bundle savedInstanceState){super.OnCreate(savedInstanceState);setContentView(R.Layout.activity_main);mListView = (ListView)findViewById(R.id.lv_main);new MyAsyncTask().execute(URL);
}
private List<MyBean> getJsonData(String url){//将Url的Json数据转化为所封装的MyBean对象List<MyBean> myBeanList = new ArrayList<>();try{String jsonString = readStream(new URL(url).openStream());//上述语句功能与url.openConnection().getInputStream()相同,//可根据URL直接联网获取网络数据,简单粗暴,返回值类型为InputStreamJSONObject jsonObject;MyBean myBean;try{jsonObject = new jsonObject(jsonString);JSONArray jsonArray = jsonObject.getJSONArray("data");for(int i =0;i<jsonArray.length();i++){jsonObject = jsonArray.getJSONObject(i);myBean = new MyBean();myBean.MyIconUrl = jsonObject.getString("picSmall");myBean.MyTitle = jsonObject.getString("name");myBean.MyContent = jsonObject.getString("description");myBeanList.add(myBean);//循环完毕时,将所有数据加入MyBean对象中,之后就可以将数据设置在ListView中}}catch(JSONException e){e.printStackTrace();}}catch(IOException e){e.printStackTrace();}return myBeanList;
}private String readStream(InputStream is){//通过InputStream解析网页返回的数据InputSrteamReader isr;String result = "";try{String line = "";isr = new InputStream(is, "utf-8");BufferedReader br = new BufferedReader(isr);while((line = br.readLine())!= null){result+=line;}}catch(UnsupportedEncodingException e){e.printStackTrace();}catch(IOException e){e.printStackTrace();}return result;
}class MyAsyncTask extends AsyncTask<String, Void, List<MyBean>>{//实现网络的异步访问protected List<MyBean> doInBackground(String... params){return getJsonData(params[0]);}protected void onPostExecute(List<MyBean> myBean){super.onPostExecute(myBean);MyAdapter adapter = new MyAdapter(MainActivity.this, myBean );mListView.setAdapter(adapter);}
}

上述实现了ListView图文混排

接下来是对图像的异步加载:

public class ImageLoader{private ImageView mImageView;private Handler mHandler = new Handler();private Handler handler = new Handler(){public void handleMessage(Message msg){super.handleMessage(msg);mImageView.setImageBitmap((Bitmap)msg.obj);}}public void showImageByThread(ImageView imageView, String url){mImageView = imageView;new Thread(){public void run(){super.run();Bitmap bitmao = getBitmapFromURL(url);Message message = Message.obtain();message.obj = bitmap;mHandler.sendMessage(message);}}.start();}public Bitmap getBitmapFromURL(String urlStirng){Bitmap bitmap;InputStream is;try{URL url = new URL(urlStirng);HttpURLConnection connection = (HttpURLConnection)url.openConnection();is = new BufferedInputStream(connection.getInputStream());bitmap = BitmapFactory.decodeStream(is);connection.disconnect();return bitmap;}catch(java.io.IOException e){e.printStackTrace();}finally{is.close();}return null;}
}

事实上,上面的方法,在网速不是很快的时候,会出现刷新时图片错乱的现象,因为ListView的缓存机制导致图片显示错位,则只需要改进一步,在MyAdapter类中的getView()方法中增加三行代码:

     viewHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);String utl = mList.get(position).MyIconUrl;viewHolder.ivIcon.setTag(utl);new ImageLoader().showImageByThread(viewHolder.ivIcon, url);viewHolder.tvTitle.setText(mList.get(position).MyTitle);viewHolder.tvContent.setText(mList.get(position).MyContent);return convertView;

之后在ImageLoader类中handleMessage()方法中增加判断语句,最终修改为:

public class ImageLoader{private ImageView mImageView;private Handler mHandler = new Handler();private String mUrl;private Handler handler = new Handler(){public void handleMessage(Message msg){super.handleMessage(msg);if(mImageView.getTag().equals(mUrl))mImageView.setImageBitmap((Bitmap)msg.obj);}}public void showImageByThread(ImageView imageView, String url){mImageView = imageView;mUrl = url;new Thread(){public void run(){super.run();Bitmap bitmao = getBitmapFromURL(url);Message message = Message.obtain();message.obj = bitmap;mHandler.sendMessage(message);}}.start();}public Bitmap getBitmapFromURL(String urlStirng){Bitmap bitmap;InputStream is;try{URL url = new URL(urlStirng);HttpURLConnection connection = (HttpURLConnection)url.openConnection();is = new BufferedInputStream(connection.getInputStream());bitmap = BitmapFactory.decodeStream(is);connection.disconnect();return bitmap;}catch(java.io.IOException e){e.printStackTrace();}finally{is.close();}return null;}
}

一般有两种办法避免ListView的缓存特性带来的ListView的Item的错乱,一种是在BaseAdapter中设置tag,将身份验证信息与相应的Item绑定,在加载时判断身份验证信息是否正确,正确才设置图片操作,第二种,是使用成员变量,将对应的数据进行缓存,从而避免网络下载时间不确定导致的时序的混乱。大部分的异步加载错误都可以使用这两种办法解决。

使用AsyncTask()方法异步加载

public void showImageByAsyncTask(ImageView imageView, String url){new MyAsyncTask(imageView).execute(url);
}private class MyAsyncTask extends AsyncTask<String, Void, Bitmap>{private ImageView imageView;public MyAsyncTask(ImageView imageView){mImageView = imageView;}protected Bitmap doInBackground(String... params){return getBitmapFromURL(params[0]);}protected void onPostExecute(Bitmap bitmap){super.onPostExecute(bitmap);mImageView.setImageBitmap(bitmap);}
}

之后再回到MyAdapter类中,将多线程的方法加载图片的语句换掉:

     //new ImageLoader().showImageByThread(viewHolder.ivIcon, url);new ImageLoader().showImageByAsyncTask(viewHolder.ivIcon, url);

同样,AsyncTask方法也会出现刷新时图片错乱的现象,因为AsyncTask本身就是基于多线程,所以对其进行处理,修改之后:

public void showImageByAsyncTask(ImageView imageView, String url){new MyAsyncTask(imageView, url).execute(url);
}private class MyAsyncTask extends AsyncTask<String, Void, Bitmap>{private ImageView imageView;private String mUrl;public MyAsyncTask(ImageView imageView, String url){mImageView = imageView;mUrl = url;}protected Bitmap doInBackground(String... params){return getBitmapFromURL(params[0]);}protected void onPostExecute(Bitmap bitmap){super.onPostExecute(bitmap);if(mImageView.getTag().equals(mUrl))mImageView.setImageBitmap(bitmap);}
}

至此,便实现了异步加载网络图片。

Android异步加载相关推荐

  1. Android异步加载全解析之引入二级缓存

    Android异步加载全解析之引入二级缓存 为啥要二级缓存 前面我们有了一级缓存,为啥还要二级缓存呢?说白了,这就和电脑是一样的,我们电脑有内存和硬盘,内存读取速度快,所以CPU直接读取内存中的数据, ...

  2. Android:异步加载图片

    我们知道Android为了不阻塞UI线程(main线程),不允许在非UI线程中进行UI操作以及网络请求等操作,为了不阻塞UI,我们往往就要进行异步加载. 我们以异步加载图片为例子,来学习一下异步加载 ...

  3. 演化理解 Android 异步加载图片

    引用:http://www.cnblogs.com/ghj1976/archive/2011/05/06/2038738.html 下面测试使用的layout文件: 简单来说就是 LinearLayo ...

  4. Android 异步加载图片分析

    研究了android从网络上异步加载图像,现总结如下: (1)由于android UI更新支持单一线程原则,所以从网络上取数据并更新到界面上,为了不阻塞主线程首先可能会想到以下方法. 在主线程中new ...

  5. android 异步加载图片缩略图

    建一个AsyncLoadedImage类继承AsyncTask异步加载类,调用publishProgress方法更新onProgressUpdate贮存缩略图信息到Adapter.监听Adapter ...

  6. Android异步加载图像(含线程池,缓存方法)

    研究了android从网络上异步加载图像: (1)由于android UI更新支持单一线程原则,所以从网络上取数据并更新到界面上,为了不阻塞主线程首先可能会想到以下方法. 在主线程中new 一个Han ...

  7. android异步加载视频缩略图,Android 视频缩略图的缓存机制和异步加载

    关注微信号:javalearns   随时随地学Java 或扫一扫 随时随地学Java 在这次的工作开发项目中,涉及到一个视频缩略图的视频列表:这个在大家看来,制作视频缩略图就是两行代码就搞定的事.确 ...

  8. android图片异步加载图片,Android 异步加载图片分析总结

    研究了android从网络上异步加载图像,现总结如下: (1)由于android UI更新支持单一线程原则,所以从网络上取数据并更新到界面上,为了不阻塞主线程首先可能会想到以下方法. 在主线程中new ...

  9. wemall app商城源码中基于JAVA的Android异步加载图片管理器代码

    wemall doraemon是Android客户端程序,服务端采用wemall微信商城,不对原商城做任何修改,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可随意定制修改.本文分享其中 ...

最新文章

  1. Python date,datetime,time等相关操作总结
  2. Shell变量:Shell变量的定义、删除变量、只读变量、变量类型
  3. [剑指offer][JAVA]面试题第[32-2]题[从上到下打印二叉树][BFS]
  4. 记GMIC 2014
  5. 成为项目经理需要具备什么条件?
  6. 为什么Python中称__lt__、__gt__等为“富比较”方法
  7. 扫描式SSD用于公式检测,代码已开源
  8. 使用Spring配合Junit进行单元测试的总结
  9. 你真的会用ABAP, Java和JavaScript里的constructor么? 1
  10. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第1节 常用函数接口_13_常用的函数式接口_Predicate接口中的默认方法and...
  11. attention机制_Seq2seq模型中的 Attention机制
  12. 《焦虑心理学》——综述篇
  13. 基于python毕业设计毕设课题选题参考
  14. OpenCat 简评
  15. 关于屏幕分辨率适配的教程
  16. 北京大学暑期学校总结
  17. 感性认识:计算机基本工作原理
  18. Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释
  19. java outputstream 输入文件损坏问题
  20. 高数学习笔记(一):常用重要概念

热门文章

  1. 电子信息工程水声考研去向_哈工大电子与信息工程专业考研 科研方向汇总
  2. Maven install 中文乱码问题
  3. SQL工具-技术支持工具
  4. java中javamail收发邮件实现方法
  5. SoapUI 请求 https 报 javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
  6. 多环境下读取不同的配置文件
  7. HTML/CSS[收藏]
  8. 隐马尔可夫(HMM)、前/后向算法、Viterbi算法
  9. 中止取消ajax请求,IE7下的bug解决
  10. 没有日志,只有MDF文件如何恢复数据库(转)[