来自: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 mList;    private ImageLoader mImageLoader;    private int mStart, mEnd;//listview屏幕可视范围内的第一条item和最后一个item    public static String URLS[];//设置一个数组,用来保存所有图片的URL    private boolean mFirstIn;//判断是否是第一次启动程序    public NewsAdapter(Context context, List 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 mCache;    private ListView mListView;    private Set mTasks;//从start到end范围每次执行加载图片任务的集合    public ImageLoader(ListView listView)    {        mListView = listView;        mTasks = new HashSet();        int maxMemory = (int) Runtime.getRuntime().maxMemory();//获取最大可用内存        int cacheSize = maxMemory/4;//设置缓存的大小        mCache = new LruCache(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    {        //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 getJsonData(String url)    {        List newsBeanList = new ArrayList();//保存解析出来的所有的数据        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>    {        @Override        protected List doInBackground(String... params) {                     return getJsonData(params[0]);        }        @Override        protected void onPostExecute(List result) {            super.onPostExecute(result);            // 访问网络并解析json成功后返回结果,即我们设置的List            NewsAdapter adapter = new NewsAdapter(MainActivity.this, result, mListView);            mListView.setAdapter(adapter);        }    }}

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

更多相关文章

  1. Picasso源码解析
  2. 自定义进度条,progressBar 背景为.9图片
  3. Android(安卓)通过字符串资源名获取资源id
  4. Android超好用的图片加载框架
  5. Android加载Class的思考
  6. 关于ImageView图片宽高比的问题
  7. Android有效解决加载大图片时内存溢出的问题[转]
  8. android yuv摄像
  9. Android(安卓)嵌入式 linux 去掉启动时闪烁的光标 和制作启动LOG

随机推荐

  1. 关于移动端踩过的坑
  2. Android NDK 使用第一步,编译c文件,声明jni
  3. 谈谈Android的那些事
  4. 从Android界面开发谈起
  5. 如何在Android中利用AIDL添加service
  6. Android(安卓)Material Design
  7. Android(安卓)新手扫盲
  8. 第八章 Android(安卓)开发常见的UI布局
  9. android 小知识
  10. Windows下Android平台搭建_2