转载请注明出处:http://blog.csdn.net/wei_chong_chong/article/details/50880293
下面实现一个异步加载网络图片的例子,加载的图片使用ListIView显示出来
异步加载图片有两种方式,多线程,和AsyncTask,其实大家都知道AsyncTask底层也是多线程来实现的
第一步。布局文件
主布局文件是一个ListVIew
<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" tools:context="com.example.android.MainActivity" > <ListView android:id="@+id/lv_news" android:layout_width="match_parent" android:layout_height="match_parent" > </ListView> </RelativeLayout>item的布局文件:
item_layout.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="wrap_content" android:orientation="horizontal" android:padding="4dp" > <ImageView android:id="@+id/iv_newsimage" android:layout_width="64dp" android:layout_height="64dp" android:paddingLeft="2dp" android:src="@drawable/ic_launcher" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:paddingLeft="4dp" > <TextView android:id="@+id/tv_newstitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:maxLines="1" android:text="TextView" android:textSize="15sp" /> <TextView android:id="@+id/tv_newscontent" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:maxLines="3" android:text="TextView" android:textSize="10dp" /> </LinearLayout> </LinearLayout>
创建一个NewsBean的类
public class NewsBean { public String newsIconUrl; public String newstitle; public String newscontent; }
下面的操作在MainActivity中:
创建成员变量
private ListView mLisView; private String URL = "http://www.imooc.com/api/teacher?type=4&num=30";
然后在MainActivity中创建内部类实现异步访问网络数据:
/** * 实现网络的异步访问 * @author Administrator * */ class MyAsyncTask extends AsyncTask<String, Void, List<NewsBean>>{ @Override protected List<NewsBean> doInBackground(String... params) { // TODO Auto-generated method stub return getJsonData(params[0]); } @Override protected void onPostExecute(List<NewsBean> result) { // TODO Auto-generated method stub super.onPostExecute(result); NewsAdapter adapter = new NewsAdapter(MainActivity.this, result); mLisView.setAdapter(adapter); } }上面的代码在doInBackground方法中调用
getJsonData(params[0]);方法,所以要创建一个getJsonData()的方法
/** * 将url对应的JSON格式数据转化为我们所封装的NewsBean对象 * @param url * @return */ private List<NewsBean> getJsonData(String url){ List<NewsBean> newsBeanList = new ArrayList<NewsBean>(); try { JSONObject jsonobject ; JSONArray jsonArray ; NewsBean newsBean; String jsonString = readStream(new URL(url).openStream()); jsonobject = new JSONObject(jsonString); jsonArray = jsonobject.getJSONArray("data"); for (int i = 0; i < jsonArray.length(); i++) { jsonobject = jsonArray.getJSONObject(i); newsBean = new NewsBean(); newsBean.newsIconUrl = jsonobject.getString("picSmall"); newsBean.newstitle = jsonobject.getString("name"); newsBean.newscontent = jsonobject.getString("description"); newsBeanList.add(newsBean); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } /** * new URL(url).openStream()这句话功能与url.openConnection().getInputStream()相同 * 可根据URL直接联网获取网络数据,简单粗暴,返回值类型为InputStream */ return newsBeanList; }在上面的getJsonData方法中我们有用到String jsonString = readStream(new URL(url).openStream());获取网络数据
创建readStream方法
/** * 通过is解析网页返回的数据 * @param is * @return */ private String readStream(InputStream is){ InputStreamReader isr ; String result = ""; String line = ""; try { isr = new InputStreamReader(is,"utf-8"); BufferedReader br = new BufferedReader(isr); while((line = br.readLine())!=null){ result += line; } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; }
使用异步加载访问网络
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLisView = (ListView) findViewById(R.id.lv_news); new MyAsyncTask().execute(URL); }
onPostExecute()
方法中将获取到的网络数据传递给NewsAdapter并在ListView中显示出来
创建一个NewsAdapter类
下面的改动在NewsAdapter中
创建两个成员变量:
private List<NewsBean> mList; private LayoutInflater mInflater;创建构造函数:
public NewsAdapter(Context context,List<NewsBean> data){ mList = data; mInflater = LayoutInflater.from(context); }getCount(),getItem(),getItemId()方法
@Override public int getCount() { // TODO Auto-generated method stub return mList.size(); }
<pre code_snippet_id="1608833" snippet_file_name="blog_20160313_4_9669111" name="code" class="java">@Override public Object getItem(int position) { // TODO Auto-generated method stub return mList.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; }
@Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub 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_newsimage); viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tv_newstitle); viewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_newscontent); convertView.setTag(viewHolder); }else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.ivIcon.setImageResource(R.drawable.ic_launcher); String url = mList.get(position).newsIconUrl; viewHolder.ivIcon.setTag(url);//将imageView显示的图片和url进行一个绑定,避免ListView的缓存图片对正确图片带来的影响 //使用多线程方式加载图片 //new ImageLoader().showImageByThread(viewHolder.ivIcon, mList.get(position).newsIconUrl); //使用AsyncTask加载网络图片 new ImageLoader().showImageByAsyncTask(viewHolder.ivIcon, mList.get(position).newsIconUrl); viewHolder.tvTitle.setText(mList.get(position).newstitle); viewHolder.tvContent.setText(mList.get(position).newscontent); return convertView; }上面getView方法中,为了提高listview显示的效率,避免重绘,创建内部类:
class ViewHolder{ public TextView tvTitle,tvContent; public ImageView ivIcon; }
下面的改动在ImageLoader类中:‘
创建成员变量
private ImageView mImageView; private String mUrl;方法一创建方法线程方法使用多线程加载网络图片
public void showImageByThread(ImageView imageView,final String url){ mImageView = imageView; mUrl = url; new Thread(){ @Override public void run() { // TODO Auto-generated method stub Bitmap bitmap = getBitmapFromURL(url); Message message = Message.obtain(); message.obj = bitmap; mHandler.sendMessage(message); } }.start(); }
创建方法从网络中获取图片
public Bitmap getBitmapFromURL(String urlString){ Bitmap bitmap; InputStream is = null; try { URL url = new URL(urlString); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); is = new BufferedInputStream(connection.getInputStream()); bitmap = BitmapFactory.decodeStream(is); connection.disconnect(); //Thread.sleep(1000);//模拟网速不好的情况,实际应用中要去掉 return bitmap; } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; }
private Handler mHandler = new Handler(){ public void handleMessage(android.os.Message msg) { super.handleMessage(msg); if(mImageView.getTag().equals(mUrl) ){ mImageView.setImageBitmap((Bitmap) msg.obj); } }; };
/** * 使用AsyncTask加载网络图片 */ public void showImageByAsyncTask(ImageView imageView ,String url){ //从缓存中取出图片 Bitmap bitmap = getBitmapFromCache(url); if (bitmap == null) { //如果缓存中没有,就使用异步从网络中下载 new NewsAsyncTask(imageView,url).execute(url); }else { //如果缓存中有就直接从缓存中读取 imageView.setImageBitmap(bitmap); } }创建异步加载类ASyncTask
/** * 使用AsyncTask加载网络图片 */ public void showImageByAsyncTask(ImageView imageView ,String url){
new NewsAsyncTask(imageView,url).execute(url); } private class NewsAsyncTask extends AsyncTask<String, Void, Bitmap>{ private ImageView mImageView; private String mUrl; public NewsAsyncTask(ImageView imageView,String url){ mImageView = imageView; mUrl = url; } @Override protected Bitmap doInBackground(String... params) { String url = params[0]; Bitmap bitmap = getBitmapFromURL(params[0]);//从网络获取图片 return bitmap; } @Override protected void onPostExecute(Bitmap result) { // TODO Auto-generated method stub if (mImageView.getTag().equals(mUrl)) { mImageView.setImageBitmap(result); } } }
MainActivity:
package com.example.android; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.ListView; public class MainActivity extends Activity { private ListView mLisView; private String URL = "http://www.imooc.com/api/teacher?type=4&num=30"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLisView = (ListView) findViewById(R.id.lv_news); new MyAsyncTask().execute(URL); } /** * 将url对应的JSON格式数据转化为我们所封装的NewsBean对象 * @param url * @return */ private List<NewsBean> getJsonData(String url){ List<NewsBean> newsBeanList = new ArrayList<NewsBean>(); try { JSONObject jsonobject ; JSONArray jsonArray ; NewsBean newsBean; String jsonString = readStream(new URL(url).openStream()); jsonobject = new JSONObject(jsonString); jsonArray = jsonobject.getJSONArray("data"); for (int i = 0; i < jsonArray.length(); i++) { jsonobject = jsonArray.getJSONObject(i); newsBean = new NewsBean(); newsBean.newsIconUrl = jsonobject.getString("picSmall"); newsBean.newstitle = jsonobject.getString("name"); newsBean.newscontent = jsonobject.getString("description"); newsBeanList.add(newsBean); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } /** * new URL(url).openStream()这句话功能与url.openConnection().getInputStream()相同 * 可根据URL直接联网获取网络数据,简单粗暴,返回值类型为InputStream */ return newsBeanList; } /** * 通过is解析网页返回的数据 * @param is * @return */ private String readStream(InputStream is){ InputStreamReader isr ; String result = ""; String line = ""; try { isr = new InputStreamReader(is,"utf-8"); BufferedReader br = new BufferedReader(isr); while((line = br.readLine())!=null){ result += line; } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; } /** * 实现网络的异步访问 * @author Administrator * */ class MyAsyncTask extends AsyncTask<String, Void, List<NewsBean>>{ @Override protected List<NewsBean> doInBackground(String... params) { // TODO Auto-generated method stub return getJsonData(params[0]); } @Override protected void onPostExecute(List<NewsBean> result) { // TODO Auto-generated method stub super.onPostExecute(result); NewsAdapter adapter = new NewsAdapter(MainActivity.this, result); mLisView.setAdapter(adapter); } } }
<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">public class NewsAdapter extends BaseAdapter{</span>
private List<NewsBean> mList; private LayoutInflater mInflater; public NewsAdapter(Context context,List<NewsBean> data){ mList = data; mInflater = LayoutInflater.from(context); } @Override public int getCount() { // TODO Auto-generated method stub return mList.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return mList.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub 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_newsimage); viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tv_newstitle); viewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_newscontent); convertView.setTag(viewHolder); }else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.ivIcon.setImageResource(R.drawable.ic_launcher); String url = mList.get(position).newsIconUrl; viewHolder.ivIcon.setTag(url);//将imageView显示的图片和url进行一个绑定,避免ListView的缓存图片对正确图片带来的影响 //使用多线程方式加载图片 //new ImageLoader().showImageByThread(viewHolder.ivIcon, mList.get(position).newsIconUrl); //使用AsyncTask加载网络图片 new ImageLoader().showImageByAsyncTask(viewHolder.ivIcon, mList.get(position).newsIconUrl); viewHolder.tvTitle.setText(mList.get(position).newstitle); viewHolder.tvContent.setText(mList.get(position).newscontent); return convertView; } class ViewHolder{ public TextView tvTitle,tvContent; public ImageView ivIcon; } }图片加载类:
package com.example.android; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Handler; import android.os.Message; import android.widget.ImageView; /** * ImageLoader专门用于处理图片加载的类 * @author Administrator * */ public class ImageLoader { <span style="white-space:pre"> </span>private ImageView mImageView; <span style="white-space:pre"> </span>private String mUrl; <span style="white-space:pre"> </span>/** <span style="white-space:pre"> </span> * 使用多线程加载图片 <span style="white-space:pre"> </span> */ <span style="white-space:pre"> </span>private Handler mHandler = new Handler(){ <span style="white-space:pre"> </span>public void handleMessage(android.os.Message msg) { <span style="white-space:pre"> </span>super.handleMessage(msg); <span style="white-space:pre"> </span>if(mImageView.getTag().equals(mUrl) ){ <span style="white-space:pre"> </span>mImageView.setImageBitmap((Bitmap) msg.obj); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>}; <span style="white-space:pre"> </span>}; <span style="white-space:pre"> </span>public void showImageByThread(ImageView imageView,final String url){ <span style="white-space:pre"> </span>mImageView = imageView; <span style="white-space:pre"> </span>mUrl = url; <span style="white-space:pre"> </span>new Thread(){ <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>public void run() { <span style="white-space:pre"> </span>// TODO Auto-generated method stub <span style="white-space:pre"> </span>Bitmap bitmap = getBitmapFromURL(url); <span style="white-space:pre"> </span>Message message = Message.obtain(); <span style="white-space:pre"> </span>message.obj = bitmap; <span style="white-space:pre"> </span>mHandler.sendMessage(message); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>}.start(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public Bitmap getBitmapFromURL(String urlString){ <span style="white-space:pre"> </span>Bitmap bitmap; <span style="white-space:pre"> </span>InputStream is = null; <span style="white-space:pre"> </span>try { <span style="white-space:pre"> </span>URL url = new URL(urlString); <span style="white-space:pre"> </span>HttpURLConnection connection = (HttpURLConnection) url.openConnection(); <span style="white-space:pre"> </span>is = new BufferedInputStream(connection.getInputStream()); <span style="white-space:pre"> </span>bitmap = BitmapFactory.decodeStream(is); <span style="white-space:pre"> </span>connection.disconnect(); <span style="white-space:pre"> </span>//Thread.sleep(1000);//模拟网速不好的情况,实际应用中要去掉 <span style="white-space:pre"> </span>return bitmap; <span style="white-space:pre"> </span>} catch (MalformedURLException e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} catch (IOException e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>}finally{ <span style="white-space:pre"> </span>try { <span style="white-space:pre"> </span>is.close(); <span style="white-space:pre"> </span>} catch (IOException e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return null; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>/** <span style="white-space:pre"> </span> * 使用AsyncTask加载网络图片 <span style="white-space:pre"> </span> */ <span style="white-space:pre"> </span>public void showImageByAsyncTask(ImageView imageView ,String url){ <span style="white-space:pre"> </span>new NewsAsyncTask(imageView,url).execute(url); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>private class NewsAsyncTask extends AsyncTask<String, Void, Bitmap>{ <span style="white-space:pre"> </span>private ImageView mImageView; <span style="white-space:pre"> </span>private String mUrl; <span style="white-space:pre"> </span>public NewsAsyncTask(ImageView imageView,String url){ <span style="white-space:pre"> </span>mImageView = imageView; <span style="white-space:pre"> </span>mUrl = url; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>protected Bitmap doInBackground(String... params) { <span style="white-space:pre"> </span>// TODO Auto-generated method stub <span style="white-space:pre"> </span>return getBitmapFromURL(mUrl); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>protected void onPostExecute(Bitmap result) { <span style="white-space:pre"> </span>// TODO Auto-generated method stub <span style="white-space:pre"> </span>if (mImageView.getTag().equals(mUrl)) { <span style="white-space:pre"> </span>mImageView.setImageBitmap(result); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} }