转载请注明出处: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;
}
在onCreate方法中
使用异步加载访问网络
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLisView = (ListView) findViewById(R.id.lv_news);
new MyAsyncTask().execute(URL);
}
在MainActivity中的内部类中
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;
}
getView方法:
@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类实现图片的异步加载
下面的改动在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;
}
创建成员变量:在主线程中更新UI
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加载网络图片
/**
* 使用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);
}
}
}
NewsAdapter
<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>}
}