来自:http://www.imooc.com/video/7871 
推荐大家去学习这个视频,讲解的很不错。 
慕课网提供了一个json网址可以用来学习:http://www.imooc.com/api/teacher?type=4&num=30。我们的任务就是建立一个listview,将json提供的一些参数,主要是name,picSmall,description显示出来,效果图如下: 

主要思路如下:listview中图片的加载,程序中使用了两种方式,一种是使用Thread类,一种是使用AsyncTask,为了提高listview滑动的效率,并节省流量,使用了LruCache类,更改加载图片的处理逻辑为:当滑动listview时不加载图片,停止滑动listview时加载界面可视范围内的图片。具体程序如下: 
1 NewsBean.Java listview每一项的封装类

 package com.example.imoocnews;

 public class NewsBean {
private String newsIconUrl;//图片的网址即picSmall
private String newsTitle;//图片的标题即json中的name属性
private String newsContent;//图片的内容即json中的description public NewsBean(String newsIconUrl, String newsTitle, String newsContent)
{
this.newsIconUrl = newsIconUrl;
this.newsTitle = newsTitle;
this.newsContent = newsContent;
}
public String getNewsIconUrl() {
return newsIconUrl;
}
public void setNewsIconUrl(String newsIconUrl) {
this.newsIconUrl = newsIconUrl;
}
public String getNewsTitle() {
return newsTitle;
}
public void setNewsTitle(String newsTitle) {
this.newsTitle = newsTitle;
}
public String getNewsContent() {
return newsContent;
}
public void setNewsContent(String newsContent) {
this.newsContent = newsContent;
} }

2 适配器NewsAdapter.java

 package com.example.imoocnews;

 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.ListView;
import android.widget.TextView;
import android.widget.AbsListView; /**
* listview的适配器,包括上下文对象和数据源
* 提高listview的效率:当listview滚动时不去加载可见项图片,停止滚动后再开始加载
*/
public class NewsAdapter extends BaseAdapter implements AbsListView.OnScrollListener{ private LayoutInflater mInflater;
private List<NewsBean> mList;
private ImageLoader mImageLoader;
private int mStart, mEnd;//listview屏幕可视范围内的第一条item和最后一个item
public static String URLS[];//设置一个数组,用来保存所有图片的URL
private boolean mFirstIn;//判断是否是第一次启动程序 public NewsAdapter(Context context, List<NewsBean> data, ListView listView) {
mInflater = LayoutInflater.from(context);
this.mList = data;
mImageLoader = new ImageLoader(listView);//在这里初始化,能够保证只有一个imageloader的实例,即只有一个LruCache的实例
URLS = new String[data.size()];
for (int i = 0; i < data.size(); i++) {
URLS[i] = data.get(i).getNewsIconUrl();//将data中的每一个URL赋值给数组
}
listView.setOnScrollListener(this);
mFirstIn = true;//写在构造函数中,第一次调用newsAdapter时表示第一次启动程序,显示listview
} @Override
public int getCount() {
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) {
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item, null);
holder = new ViewHolder();
holder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon);
holder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);
holder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);
convertView.setTag(holder);
}else {
holder = (ViewHolder) convertView.getTag();
}
//holder.ivIcon.setImageResource(R.drawable.ic_launcher);
String url = mList.get(position).getNewsIconUrl();
holder.ivIcon.setTag(url);//给ImageView设置标志,即对应的图片网址
//利用thread类实现异步加载图片,我们这里将其注释,使用AsyncTask的方式
//new ImageLoader().showImageByThread(holder.ivIcon, mList.get(position).getNewsIconUrl());
mImageLoader.showImages(holder.ivIcon, url); holder.tvTitle.setText(mList.get(position).getNewsTitle());
holder.tvContent.setText(mList.get(position).getNewsContent());
return convertView;
}
class ViewHolder
{
public ImageView ivIcon;
public TextView tvTitle, tvContent;
}
/*
* 当listview滑动的时候调用
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
mStart = firstVisibleItem;
mEnd = mStart + visibleItemCount;
//只在第一次加载的时候调用
if (mFirstIn && visibleItemCount >0) {//表示第一次加载listview并且已经绘制了可见范围内的item
mImageLoader.loadImages(mStart, mEnd);
mFirstIn = false;//加载图片后即设为false
}
} /*
* 当listview滑动状态变化时调用
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {//listview停止滚动
//加载可见项
mImageLoader.loadImages(mStart, mEnd); }else {
//停止加载任务
mImageLoader.cancelAllTasks();
} } }

3 访问图片的实现ImageLoader.java

 package com.example.imoocnews;

 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 java.util.HashSet;
import java.util.Set; import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.LruCache;
import android.widget.ImageView;
import android.widget.ListView; public class ImageLoader {
private ImageView mImageView;
private String url;
//当图片加载过后就将图片缓存到本地,下次便不用重新联网获取,直接从本地缓存获取即可,一个图片即string url --> bitmap
private LruCache<String, Bitmap> mCache;
private ListView mListView;
private Set<NewsAsyncTask> mTasks;//从start到end范围每次执行加载图片任务的集合 public ImageLoader(ListView listView)
{
mListView = listView;
mTasks = new HashSet<ImageLoader.NewsAsyncTask>();
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();
}
};
}
/**
* 将已联网获取成功的图片加入到缓存中
* @param bitmap
*/
public void addBitmapToCache(String url, Bitmap bitmap)
{
//在将图片缓存到本地之前要判断这个图片是否已经缓存过了
if (getBitmapFromCache(url) == null) {
mCache.put(url, bitmap);
}
}
/**
* 通过URL从缓存中取出相应的图片
*/
public Bitmap getBitmapFromCache(String url)
{
return mCache.get(url);
} private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
super.handleMessage(msg);
//通过tag使得ImageView和它对应的URL绑定,这样在上下滑动listview时ImageView显示的图片就始终是正确的
//否则,由于listview的缓存机制,ImageView会先显示出上次加载成功时的图片,然后再显示正确的图片
if (mImageView.getTag().equals(url)) {
mImageView.setImageBitmap((Bitmap) msg.obj);//使用handler在主线程中更新UI,并将URL对应的图片设置给控件imageview
} }
}; /**
* 通过使用Thread的方式从网络上获取图片
*/
public void showImageByThread(ImageView imageView, final String iconUrl)
{
mImageView = imageView;
url = iconUrl;
new Thread(){
@Override
public void run() {
// 在新的进程中实现图片的加载
super.run();
//从url中获得bitmap,将bitmap发送给主线程
Bitmap bitmap = getBitmapFromUrl(iconUrl);
Message message = Message.obtain();
message.obj = bitmap;
mHandler.sendMessage(message);
}
}.start();
}
public Bitmap getBitmapFromUrl(String urlString)
{
InputStream is = null;
Bitmap bitmap;
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;
} /**
* 加载listview可见范围内的所有图片
*
*/
public void loadImages(int start, int end)
{
for (int i = start; i < end; i++) {
String url = NewsAdapter.URLS[i];
//看是否能从缓存中取出对应的图片
Bitmap bitmap = getBitmapFromCache(url);
//如果缓存中没有,就要对每个url执行异步加载任务去获取图片
if (bitmap == null) {
NewsAsyncTask task = new NewsAsyncTask(url);
task.execute(url);
mTasks.add(task); }else {
//如果缓存中存在此图片,直接将其设置给对应的imageview即可
//因为我们之前给imageview设置的tag就是URL,可以利用findViewWithTag直接在这里获取到
ImageView imageView = (ImageView) mListView.findViewWithTag(url);
imageView.setImageBitmap(bitmap);
}
}
}
/**
* 取消所有正在进行的图片加载任务
*/
public void cancelAllTasks()
{
if (mTasks != null) {
for(NewsAsyncTask task : mTasks)
{
task.cancel(false);
}
}
} public void showImages(ImageView imageView, String iconUrl)
{
//是否能从缓存中取出对应的图片
Bitmap bitmap = getBitmapFromCache(iconUrl);
if (bitmap == null) {
imageView.setImageResource(R.drawable.ic_launcher);//显示默认图片
}else {
//如果缓存中存在此图片,直接将其设置给对应的imageview即可
imageView.setImageBitmap(bitmap);
} }
/**
* 使用AsyncTask实现图片的异步加载
*/
class NewsAsyncTask extends AsyncTask<String, Void, Bitmap>
{
//private ImageView mImageView;
private String mUrl;
public NewsAsyncTask(String url) {
// mImageView = image;
mUrl = url;
}
@Override
protected Bitmap doInBackground(String... params) {
String url = params[0];
Bitmap bitmap = getBitmapFromUrl(url);//从网络上得到图片
if (bitmap != null) {
addBitmapToCache(url, bitmap);//获取图片成功将图片存入缓存中
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
// 后台获取图片的任务完成时调用此方法
super.onPostExecute(bitmap);
//给imageview设置图片
ImageView imageView = (ImageView) mListView.findViewWithTag(mUrl);
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
mTasks.remove(this);
}
} }

4. MainActivity.java

 package com.example.imoocnews;

 import java.io.BufferedReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
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.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView; public class MainActivity extends Activity { private ListView mListView;
private static String jsonURL = "http://www.imooc.com/api/teacher?type=4&num=30";//json数据网址 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.lv_main);
new NewsAsyncTask().execute(jsonURL);
}
/**
* 将URL网址上的json数据转化为我们所需的newsbean对象
* @return
*/
private List<NewsBean> getJsonData(String url)
{
List<NewsBean> newsBeanList = new ArrayList<NewsBean>();//保存解析出来的所有的数据
try {
//获取到json字符串
String jsonString = readStream(new URL(url).openStream());//和url.openConnection().getInputStream()一样
//Log.d("MainActivity", jsonString);
//将获取到的json字符串变为jsonObject对象,打开网址可以看出data节点是一个jsonArray,array里面存放了一个个的jsonObject
NewsBean newsBean;
JSONObject jsonObject;
String newsUrl = null;
String newsTitle = null;
String newsContent = null;
jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.getJSONArray("data");
for (int i = 0; i < jsonArray.length(); i++) {
jsonObject = jsonArray.getJSONObject(i);
newsUrl = jsonObject.getString("picSmall");//图片网址
newsTitle = jsonObject.getString("name");//title
newsContent = jsonObject.getString("description");//content
newsBean = new NewsBean(newsUrl, newsTitle, newsContent);
newsBeanList.add(newsBean);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return newsBeanList;
} /**
* 解析网络返回的数据
*/
private String readStream(InputStream is)
{
InputStreamReader isReader;
String result = "";
String line = "";
try {
isReader = new InputStreamReader(is, "utf-8");//将字节流转化为字符流
BufferedReader buffReader = new BufferedReader(isReader);//从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取
while ((line = buffReader.readLine()) != null) {
result += line;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} return result;
}
/**
* 构造一个AsyncTask,传入String类型的URL,返回一个NewsBean对象,每一个对象就是
* listview中的每一行数据,包括一个icon,title,content
*/
class NewsAsyncTask extends AsyncTask<String, Void, List<NewsBean>>
{ @Override
protected List<NewsBean> doInBackground(String... params) {
return getJsonData(params[0]);
} @Override
protected void onPostExecute(List<NewsBean> result) {
super.onPostExecute(result);
// 访问网络并解析json成功后返回结果,即我们设置的List<NewsBean>
NewsAdapter adapter = new NewsAdapter(MainActivity.this, result, mListView);
mListView.setAdapter(adapter);
} } }

源码在这里:http://download.csdn.net/detail/hnyzwtf/9418993

Android异步加载访问网络图片-解析json的更多相关文章

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

    原文:http://www.cnblogs.com/ghj1976/archive/2011/05/06/2038738.html#3018499 在学习"Android异步加载图像小结&q ...

  2. [转载]Android 异步加载解决方案

    2013-12-25 11:15:47 Android 异步加载解决方案,转载自: http://www.open-open.com/lib/view/open1345017746897.html 请 ...

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

    演化理解 Android 异步加载图片(转)http://www.cnblogs.com/CJzhang/archive/2011/10/20/2218474.html

  4. android 异步加载框架 原理完全解析

    一.手写异步加载框架MyAsycnTask(核心原理) 1.我为大家手写了一个异步加载框架,涵盖了异步加载框架核心原理. MyAsycnTask.java import android.os.Hand ...

  5. Android异步加载

    一.为什么要使用异步加载? 1.Android是单线程模型 2.耗时操作阻碍UI线程 二.异步加载最常用的两种方式 1.多线程.线程池 2.AsyncTask 三.实现ListView图文混排 3-1 ...

  6. android异步加载图片并缓存到本地实现方法

    图片过多造成内存溢出,这个是最不容易解决的,要想一些好的缓存策略,比如大图片使用LRU缓存策略或懒加载缓存策略.今天首先介绍一下本地缓存图片     在android项目中访问网络图片是非常普遍性的事 ...

  7. Android 异步加载解决方案

    Android的Lazy Load主要体现在网络数据(图片)异步加载.数据库查询.复杂业务逻辑处理以及费时任务操作导致的异步处理等方面.在介绍Android开发过程中,异步处理这个常见的技术问题之前, ...

  8. 实例演示Android异步加载图片

    本文给大家演示异步加载图片的分析过程.让大家了解异步加载图片的好处,以及如何更新UI.首先给出main.xml布局文件:简单来说就是 LinearLayout 布局,其下放了2个TextView和5个 ...

  9. 实例演示Android异步加载图片(转)

    本文给大家演示异步加载图片的分析过程.让大家了解异步加载图片的好处,以及如何更新UI.首先给出main.xml布局文件:简单来说就是 LinearLayout 布局,其下放了2个TextView和5个 ...

随机推荐

  1. 2015年---移动端webapp知识总结

    没想到这样又过了5个月了,近期辞职了,所以我有时间来做总结. 这段时间里我学习了很多东西,而且都是我们移动端webapp的同学值得去学习的. 我先告诉大家我这次写的总结,有以下内容: 1.body的背 ...

  2. WCF 已知类型和泛型解析程序 KnownType

    数据协定继承 已知类型和泛型解析程序 Juval Lowy 下载代码示例 自首次发布以来,Windows Communication Foundation (WCF) 开发人员便必须处理数据协定继承方 ...

  3. [译]了解AngularJS $resource

    原文: https://learnable.com/books/angularjs-novice-to-ninja/preview/understanding-angularjs-resource-e ...

  4. 编译本地64位版本的hadoop-2.6.0

     官方提供的hadoop-2.x版本貌似都是32位的,在64位机子下使用可能会报错,最好使用官方提供的源码进行本地编译,编译成适合本地硬件环境的64位软件包. 关于native  Hadoop是使用J ...

  5. Ubuntu10.04下安装Ns2的一系列错误及解决方案

    安装之前改一下nam1.11下的agent.h文件73行 Null改为0 第一个错误: xxx configuration: Syntax error: Unterminated quoted str ...

  6. POJ 2155 Matrix

    二维树状数组....                          Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissio ...

  7. windows server 2008 R2 SP1 安装exchange 2010

    一. 先决条件 若在windows server R2 SP1企业版系统上典型安装exchange server2010 SP3,则需要提前确定一下先决条件 AD域环境,域和林的功能级别必须是wind ...

  8. Web服务精讲–搭个 Web 服务器(二)

    导读 曾几何时,你所选择的 Python Web 框架会限制你所可选择的 Web 服务器,反之亦然.如果某个框架及服务器设计用来协同工作的,那么一切正常. 在第一部分中,我提出了一个问题:“如何在你刚 ...

  9. 流畅web动画的十个法则

    from me: web动画能够带来一个非常酷炫的效果,能够让页面有一个更好的用户体验.对于良好的动画性能没有高招,除了将大量的时间放在测试和优化,当然最重要的还是要易于维护. 流畅web动画的十大法 ...

  10. hiho #1318 非法二进制数

    #1318 : 非法二进制数 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 如果一个二进制数包含连续的两个1,我们就称这个二进制数是非法的. 小Hi想知道在所有 n 位 ...