异步加载网络图片(多线程,和AsyncTask)

转载请注明出处: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>}
}






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值