activity_main.xml
<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.myasynctask.MainActivity" >
<ListView
android:id="@+id/listview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</ListView>
</RelativeLayout>
每个条目的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dp" >
<ImageView
android:id="@+id/iv_imageview"
android:layout_width="64dp"
android:layout_height="64dp"
android:src="@drawable/ic_launcher" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="26.45"
android:gravity="center"
android:orientation="vertical"
android:paddingLeft="4dp" >
<TextView
android:id="@+id/tv_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="title" />
<TextView
android:id="@+id/tv_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="content" />
</LinearLayout>
</LinearLayout>
NewsBean
package com.example.asynctask;
public class NewsBean {
public String title;
public String content;
public String imageViewUrl;
public NewsBean(String title, String content, String imageViewUrl) {
super();
this.title = title;
this.content = content;
this.imageViewUrl = imageViewUrl;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getImageViewUrl() {
return imageViewUrl;
}
public void setImageViewUrl(String imageViewUrl) {
this.imageViewUrl = imageViewUrl;
}
public NewsBean() {
super();
// TODO Auto-generated constructor stub
}
}
MainActivity
package com.example.asynctask;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
public class MainActivity extends Activity {
//获取listview控件
private ListView listView;
//慕课网的Json字符串
private String jsonUrl = "http://www.imooc.com/api/teacher?type=4&num=30";
//加载Json字符串到本地,并且解析为本地对象数组
private List<NewsBean> newBeanlist;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化listview控件
listView = (ListView) findViewById(R.id.listview);
//开启异步任务,传递慕课网jsonUrl进行网络异步加载任务
new MyAsyncTask().execute(jsonUrl);
}
/**
* 创建异步任务,
* 参数:慕课网的jsonHttp地址
* Void没有进度显示为Void
* 返回本地对象集合
*
*/
class MyAsyncTask extends AsyncTask<String, Void, List<NewsBean>> {
@Override
protected List<NewsBean> doInBackground(String... params) {
//构建一个方法,进行网络json字符串获取,并且解析为本地对象集合
return getJsonData(jsonUrl);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(List<NewsBean> result) {
super.onPostExecute(result);
//解析完毕后,进行适配器的数据设置填充
JsonAdapter adapter = new JsonAdapter(MainActivity.this, newBeanlist);
listView.setAdapter(adapter);
}
@Override
protected void onProgressUpdate(Void... values) {
}
}
/**
* //构建一个方法,进行网络json字符串获取,并且解析为本地对象集合
* @param jsonUrl
* @return
*/
public List<NewsBean> getJsonData(String jsonUrl) {
try {
//创建url http地址
URL httpUrl = new URL(jsonUrl);
//打开http 链接
HttpURLConnection connection = (HttpURLConnection) httpUrl
.openConnection();
//设置参数 请求为get请求
connection.setReadTimeout(5000);
connection.setRequestMethod("GET");
//connection.getInputStream()得到字节输入流,InputStreamReader从字节到字符的桥梁,外加包装字符流
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
//创建字符串容器
StringBuffer sb = new StringBuffer();
String str = "";
//行读取
while ((str = bufferedReader.readLine()) != null) {
// 当读取完毕,就添加到容器中
sb.append(str);
}
//测试是否得到json字符串
Log.e("TAG", ""+sb.toString());
//创建本地对象的集合
newBeanlist = new ArrayList<NewsBean>();
// 整体是一个jsonObject
JSONObject jsonObject = new JSONObject(sb.toString());
// 键是jsonArray数组
JSONArray jsonArray = jsonObject.getJSONArray("data");
for (int i = 0; i < jsonArray.length(); i++) {
//获取jsonArray中的每个对象
JSONObject jsonObject2 = jsonArray.getJSONObject(i);
//创建本地的newsBean对象
NewsBean newsBean = new NewsBean();
//为该对象进行属性值的设置操作
newsBean.imageViewUrl = jsonObject2
.getString("picSmall");
newsBean.title = jsonObject2.getString("name");
newsBean.content = jsonObject2.getString("description");
//添加对象,组建集合
newBeanlist.add(newsBean);
}
} catch (Exception e) {
e.printStackTrace();
}
return newBeanlist;
}
}
JsonAdapter
package com.example.asynctask;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
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 JsonAdapter extends BaseAdapter {
List<NewsBean> data = new ArrayList<NewsBean>();
LayoutInflater inflater;
private ImageLoaderAsyncTask imageLoaderAsyncTask;
public JsonAdapter(Context context,List<NewsBean> data) {
super();
this.data = data;
inflater = LayoutInflater.from(context);
imageLoaderAsyncTask = new ImageLoaderAsyncTask();
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = inflater.inflate(R.layout.listview_item, null);
viewHolder.title = (TextView) convertView
.findViewById(R.id.tv_title);
viewHolder.content = (TextView) convertView
.findViewById(R.id.tv_content);
viewHolder.imageView = (ImageView) convertView
.findViewById(R.id.iv_imageview);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
String imageViewUrl = data.get(position).imageViewUrl;
//进行绑定--不会出现图片错位现象--因为viewholder是复用的,会显示复用的那个itme的图片
viewHolder.imageView.setTag(imageViewUrl);
viewHolder.title.setText(data.get(position).title);
viewHolder.content.setText(data.get(position).content);
/**
* 这个方式是通过分线程进行图片下载
*/
// new ImageLoaderThread().showImageByThread(viewHolder.imageView, data.get(position).imageViewUrl);
/**
* 这个方式是进行异步任务方式进行图片加载
*/
imageLoaderAsyncTask.showImageAsyncTask(viewHolder.imageView, data.get(position).imageViewUrl);
return convertView;
}
class ViewHolder{
public TextView title,content;
public ImageView imageView;
}
}
ImageLoaderAsyncTask
package com.example.asynctask;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.R.integer;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.LruCache;
import android.widget.ImageView;
public class ImageLoaderAsyncTask {
private LruCache<String, Bitmap> mCache;
/**构造方法初始化一个缓存*/
public ImageLoaderAsyncTask() {
super();
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory/4;
mCache = new LruCache<String, Bitmap>(cacheSize){
@Override
protected int sizeOf(String key, Bitmap value) {
//通过这个方法,获取存储的内存的大小
return value.getByteCount();
}
};
}
/**向缓存中添加图片*/
public void addBitmapToCache(String url ,Bitmap bitmap){
if (getBitmapFromCache(url) == null) {
mCache.put(url, bitmap);
}
}
/**从缓存中获取bitmap*/
public Bitmap getBitmapFromCache(String url){
return mCache.get(url);
}
/**
* 使用异步任务进行加载图片
*
*/
public void showImageAsyncTask(ImageView imageView, final String url) {
Bitmap bitmap = getBitmapFromCache(url);
//如果缓存中没有图片,就进行下载操作
if (bitmap == null) {
//讲adapter传过来的imageview和url 通过构造方法传递到异步任务中
new ImageAsyncTask(imageView,url).execute(url);
}else {
//如果缓存中有图片,就直接进行图片的设置操作
imageView.setImageBitmap(bitmap);
}
}
/**
* 开启异步任务进行下载图片
* 参数:
* 是图片的地址信息
* 没有进度显示
* 返回一个图片
* @author wyf
*
*/
class ImageAsyncTask extends AsyncTask<String, Void, Bitmap> {
/**
* 这里需要设置属性的原因是
* imageview是因为需要判断是不是绑定url,以及更新ui操作
* url需要
*/
private ImageView imageView;
private String url;
public ImageAsyncTask(ImageView imageView, String url) {
super();
this.imageView = imageView;
this.url = url;
}
@Override
protected Bitmap doInBackground(String... params) {
//多留意parm[0],因为只传过来一个url,所以就取出第一个索引值
Bitmap bitmap = getBitmapFromUrl(params[0]);
//将bitmap保存到缓存中
if (bitmap!=null) {
addBitmapToCache(params[0], bitmap);
}
return bitmap;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
//判断是不是绑定的特定的url地址,防止出现图篇错乱
if (imageView.getTag().equals(url)) {
//更新ui
imageView.setImageBitmap(bitmap);
}
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
/**
* 通过url获取网络图片
* 跟那个线程下载图片方式一样一样的
* @param urlString
* @return
*/
public Bitmap getBitmapFromUrl(String urlString) {
Bitmap bitmap = null;
InputStream inputStream = null;
try {
URL httpUrl = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) httpUrl
.openConnection();
inputStream = new BufferedInputStream(connection.getInputStream());
bitmap = BitmapFactory.decodeStream(inputStream);
connection.disconnect();
return bitmap;
} catch (Exception e) {
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bitmap;
}
}
*****************************************************优化二*******************************************
主activity变化
JsonAdapter adapter = new JsonAdapter(MainActivity.this, newBeanlist,listView);
JsonAdapter
package com.example.asynctask;
import java.util.ArrayList;
import java.util.List;
import android.R.integer;
import android.R.menu;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class JsonAdapter extends BaseAdapter implements OnScrollListener {
List<NewsBean> data = new ArrayList<NewsBean>();
LayoutInflater inflater;
private ImageLoaderAsyncTask imageLoaderAsyncTask;
private int mStart;
private int mEnd;
private boolean myFirst;
// 用来保存所有图片的url地址信息
public static String[] URLS;
public JsonAdapter(Context context, List<NewsBean> data, ListView listView) {
super();
myFirst = true;
this.data = data;
inflater = LayoutInflater.from(context);
imageLoaderAsyncTask = new ImageLoaderAsyncTask(listView);
URLS = new String[data.size()];
for (int i = 0; i < data.size(); i++) {
URLS[i] = data.get(i).imageViewUrl;
}
listView.setOnScrollListener(this);
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = inflater.inflate(R.layout.listview_item, null);
viewHolder.title = (TextView) convertView
.findViewById(R.id.tv_title);
viewHolder.content = (TextView) convertView
.findViewById(R.id.tv_content);
viewHolder.imageView = (ImageView) convertView
.findViewById(R.id.iv_imageview);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
String imageViewUrl = data.get(position).imageViewUrl;
// 进行绑定--不会出现图片错位现象--因为viewholder是复用的,会显示复用的那个itme的图片
viewHolder.imageView.setTag(imageViewUrl);
viewHolder.title.setText(data.get(position).title);
viewHolder.content.setText(data.get(position).content);
/**
* 这个方式是通过分线程进行图片下载
*/
// new ImageLoaderThread().showImageByThread(viewHolder.imageView,
// data.get(position).imageViewUrl);
/**
* 这个方式是进行异步任务方式进行图片加载
*/
imageLoaderAsyncTask.showImageAsyncTask(viewHolder.imageView,
data.get(position).imageViewUrl);
return convertView;
}
class ViewHolder {
public TextView title, content;
public ImageView imageView;
}
/**
* 状态切换调用 初始化不调用
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
// 记载可见项目
imageLoaderAsyncTask.loadImage(mStart, mEnd);
} else {
// 停止任务
imageLoaderAsyncTask.cancelAllTasks();
}
}
/**
* 滑动时候调用, 初始化调用
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
mStart = firstVisibleItem;
mEnd = firstVisibleItem + visibleItemCount;
// 初始化时候,itemcount为0 ,item还没有加载,需要2个方面判断
if (myFirst && visibleItemCount > 0) {
imageLoaderAsyncTask.loadImage(mStart, mEnd);
myFirst = false;
}
}
}
ImageLoaderAsyncTask
package com.example.asynctask;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import android.R.integer;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.LruCache;
import android.widget.ImageView;
import android.widget.ListView;
public class ImageLoaderAsyncTask {
private LruCache<String, Bitmap> mCache;
private ListView listView;
private Set<ImageAsyncTask> mTasks;
/** 构造方法初始化一个缓存 */
public ImageLoaderAsyncTask(ListView listView) {
super();
this.listView = listView;
mTasks = new HashSet<ImageLoaderAsyncTask.ImageAsyncTask>();
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 4;
mCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
// 通过这个方法,获取存储的内存的大小
return value.getByteCount();
}
};
}
/** 向缓存中添加图片 */
public void addBitmapToCache(String url, Bitmap bitmap) {
if (getBitmapFromCache(url) == null) {
mCache.put(url, bitmap);
}
}
/** 从缓存中获取bitmap */
public Bitmap getBitmapFromCache(String url) {
return mCache.get(url);
}
public void loadImage(int start, int end) {
for (int i = start; i < end; i++) {
String url = JsonAdapter.URLS[i];
Bitmap bitmap = getBitmapFromCache(url);
if (bitmap == null) {
// 如果缓存中没有去下载
ImageAsyncTask task = new ImageAsyncTask(url);
task.execute(url);
mTasks.add(task);
} else {
ImageView imageView = (ImageView) listView.findViewWithTag(url);
imageView.setImageBitmap(bitmap);
}
}
}
/**
* 使用异步任务进行加载图片
*
*/
public void showImageAsyncTask(ImageView imageView, final String url) {
Bitmap bitmap = getBitmapFromCache(url);
// 如果缓存中没有图片,就进行下载操作
if (bitmap == null) {
// 如果缓存中没有图片,就设置默认图片即可
imageView.setImageResource(R.drawable.ic_launcher);
} else {
// 如果缓存中有图片,就直接进行图片的设置操作
imageView.setImageBitmap(bitmap);
}
}
/**
* 开启异步任务进行下载图片 参数: 是图片的地址信息 没有进度显示 返回一个图片
*
* @author wyf
*
*/
class ImageAsyncTask extends AsyncTask<String, Void, Bitmap> {
/**
* 这里需要设置属性的原因是 imageview是因为需要判断是不是绑定url,以及更新ui操作 url需要
*/
private String url;
public ImageAsyncTask(String url) {
super();
this.url = url;
}
@Override
protected Bitmap doInBackground(String... params) {
// 多留意parm[0],因为只传过来一个url,所以就取出第一个索引值
Bitmap bitmap = getBitmapFromUrl(params[0]);
// 将bitmap保存到缓存中
if (bitmap != null) {
addBitmapToCache(params[0], bitmap);
}
return bitmap;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
// 判断是不是绑定的特定的url地址,防止出现图篇错乱
ImageView imageView = (ImageView) listView.findViewWithTag(url);
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
// if (imageView.getTag().equals(url)) {
// //更新ui
// imageView.setImageBitmap(bitmap);
// }
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
/**
* 通过url获取网络图片 跟那个线程下载图片方式一样一样的
*
* @param urlString
* @return
*/
public Bitmap getBitmapFromUrl(String urlString) {
Bitmap bitmap = null;
InputStream inputStream = null;
try {
URL httpUrl = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) httpUrl
.openConnection();
inputStream = new BufferedInputStream(connection.getInputStream());
bitmap = BitmapFactory.decodeStream(inputStream);
connection.disconnect();
return bitmap;
} catch (Exception e) {
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bitmap;
}
/**
* ' 取消
*/
public void cancelAllTasks() {
if (mTasks != null) {
for (ImageAsyncTask task : mTasks) {
// 取消
task.cancel(false);
}
}
}
}