#Android异步加载图片

来源:互联网 发布:科勒淘宝商城旗舰店 编辑:程序博客网 时间:2024/06/05 00:12

一、概述
Android中异步加载图片的方式有俩种,此文通过从服务器取出的Json数据后,通过这俩种方式去加载服务器的图片数据。

二、案例描述:
这里写图片描述

三、实现编码思路

1、写布局2、取到服务器的Json转成JavaBean保存在List中当数据源3、在适配器中把数据源对应显示在ListView4、在适配器显示图片时开启异步线程去服务器读取照片5、图片缓存优化下

1、布局xml文件代码

就一个简单的ListView + 每一个Item的布局

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"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.kuxiao.tran.studyActivity.MainActivity">    <ListView        android:id="@+id/id_lv_news"        android:layout_width="match_parent"        android:layout_height="match_parent" /></RelativeLayout>
每一个Item的布局<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:orientation="horizontal"    android:padding="4dp"    android:layout_height="wrap_content">    <ImageView        android:layout_marginLeft="5dp"        android:layout_width="64dp"        android:layout_height="64dp"        android:id="@+id/id_iv_icon"        android:src="@mipmap/ic_launcher"/>    <LinearLayout        android:layout_marginLeft="3dp"        android:orientation="vertical"        android:layout_width="match_parent"        android:layout_height="wrap_content">        <TextView            android:layout_marginTop="5dp"            android:id="@+id/id_tv_title"            android:textSize="18dp"            android:text="标题"            android:paddingLeft="3dp"            android:layout_width="match_parent"            android:layout_height="wrap_content" />        <TextView            android:layout_marginTop="3dp"            android:id="@+id/id_tv_context"            android:textSize="15dp"            android:paddingLeft="4dp"            android:text="内容"            android:layout_width="match_parent"            android:layout_height="wrap_content" />    </LinearLayout></LinearLayout>

2、取到服务器的Json转成JavaBean保存在List中当数据源

package com.kuxiao.tran.studyActivity;import android.os.AsyncTask;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.widget.ListView;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.lang.String;import java.net.MalformedURLException;import java.net.URL;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity {    private ListView mListView;    //访问服务器url    private static final String url_news = "http://172.46.159.87:8080/News/NewsAction";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mListView = (ListView) findViewById(R.id.id_lv_news);         new MyAsynctask().execute(url_news);    }     //利用异步线程访问服务取到数据源    class MyAsynctask extends AsyncTask<String, Void, List<NewsBean>> {        @Override        protected List<NewsBean> doInBackground(String... params) {            String url = params[0];            return getNewsBean(url);        }        @Override        protected void onPostExecute(List<NewsBean> newsBeans) {                 MyAdapter  myAdapter = new MyAdapter(MainActivity.this,newsBeans);                 mListView.setAdapter(myAdapter);        }    }    //解析Json数据成NewsBean    private List<NewsBean> getNewsBean(String url) {        List<NewsBean> mList = new ArrayList<>();        InputStream mIs = null;        try {            URL mUrl = new URL(url);            mIs = mUrl.openStream();            String json = getJsonFromInputStream(mIs);            Log.i("text",json);              JSONObject  jsonObject = new JSONObject(json);            JSONArray  jsonArray  = jsonObject.getJSONArray("data");            for (int i = 0; i <jsonArray.length();i++)            {                jsonObject = (JSONObject) jsonArray.get(i);                NewsBean newsBean = new NewsBean();                newsBean.setStr_context(jsonObject.getString("context"));                newsBean.setStr_icon(jsonObject.getString("Str_icon"));                newsBean.setStr_title(jsonObject.getString("title"));                mList.add(newsBean);            }        } catch (MalformedURLException e) {            e.printStackTrace();        } catch (IOException e) {        } catch (JSONException e) {            e.printStackTrace();        }        return mList;    }    //将流读取成Json字符串    private String getJsonFromInputStream(InputStream inputStream) {        String json = "";        String str;        InputStreamReader mIsr = new InputStreamReader(inputStream);        BufferedReader mBfr = new BufferedReader(mIsr);        try {            while (null != (str = mBfr.readLine())) {                json += str;            }        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                mBfr.close();            } catch (IOException e) {                e.printStackTrace();            }        }         return json;    }}

JavaBean代码

package com.kuxiao.tran.studyActivity;public class NewsBean {    private String Str_title;    private String str_context;    private String str_icon;    public String getStr_title() {        return Str_title;    }    public void setStr_title(String str_title) {        Str_title = str_title;    }    public String getStr_icon() {        return str_icon;    }    public void setStr_icon(String str_icon) {        this.str_icon = str_icon;    }    public String getStr_context() {        return str_context;    }    public void setStr_context(String str_context) {        this.str_context = str_context;    }}3、在适配器中把数据源对应显示在ListView上package com.kuxiao.tran.studyActivity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.AsyncTask;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import java.io.IOException;import java.io.InputStream;import java.net.MalformedURLException;import java.net.URL;import java.util.List;public class MyAdapter extends BaseAdapter {    private List<NewsBean> mList;//数据源    private LayoutInflater mInflater;//每一个item布局的转化    private BitmapCache mBitmapCache = null;//缓存    public MyAdapter(Context context, List<NewsBean> params) {        mInflater = LayoutInflater.from(context);        this.mList = params;        mBitmapCache = new BitmapCache();    }    @Override    public int getCount() {        return mList.size();    }    @Override    public Object getItem(int position) {        return mList.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        ViewHolder mViewHolder;        //ListView的缓存机制中判断convertView是否存在        if (convertView == null) {            mViewHolder = new ViewHolder();            convertView = mInflater.inflate(R.layout.item, null);            mViewHolder.iv_icon = (ImageView) convertView.findViewById(R.id.id_iv_icon);            mViewHolder.tv_title = (TextView) convertView.findViewById(R.id.id_tv_title);            mViewHolder.tv_context = (TextView) convertView.findViewById(R.id.id_tv_context);            convertView.setTag(mViewHolder);        } else {            mViewHolder = (ViewHolder) convertView.getTag();        }        //给对应的viewHolder对象保存的控件赋值        mViewHolder.tv_context.setText(mList.get(position).getStr_context());        mViewHolder.tv_title.setText(mList.get(position).getStr_title());        new MyAsnyctask(mViewHolder.iv_icon, position,mBitmapCache).execute(mList.get(position).getStr_icon());        return convertView;    }    //利用ViewHolder对象避免重复的findViewById寻找控件的操作    class ViewHolder {        ImageView iv_icon;        TextView tv_context;        TextView tv_title;    }}

4、在适配器显示图片时开启异步线程去服务器读取照片(第一种方式,利用Asynctask类)

在MyAdapter类中写一个内部类,代码如下

class MyAsnyctask extends AsyncTask<String, Void, Bitmap> {        private ImageView imageView;        private int position;        private static final String url = "http://172.46.159.87:8080/News/NewsImage/";        private BitmapCache mBitmapCache = null;        public MyAsnyctask(ImageView imageView, int position,BitmapCache mBitmapCache) {            this.imageView = imageView;            this.position = position;            imageView.setTag(this.position);            this.mBitmapCache = mBitmapCache;        }        @Override        protected Bitmap doInBackground(String... params) {            Bitmap bitmap;            if (mBitmapCache.getBitmap(this.position + "") == null) {                String imageName = params[0];                bitmap = getBitmap(imageName);            } else {                bitmap = mBitmapCache.getBitmap(position + "");            }            return bitmap;        }        //通过Url向服务器取图片        private Bitmap getBitmap(String imageName) {            Bitmap bitmap = null;            InputStream mIs = null;            try {                URL url = new URL(MyAsnyctask.url + imageName);                mIs = url.openStream();                bitmap = BitmapFactory.decodeStream(mIs);            } catch (MalformedURLException e) {                e.printStackTrace();            } catch (IOException e) {                e.printStackTrace();            } finally {                try {                    mIs.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            return bitmap;        }        @Override        protected void onPostExecute(Bitmap bitmap) {            if (null != imageView && null != bitmap) {                if (imageView.getTag() == position) {                    imageView.setImageBitmap(bitmap);                }            }        }    }

5、另一种方式使用Handller+子线线程的方式实现异步加载,代码如下

package com.kuxiao.tran.studyActivity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Handler;import android.os.Message;import android.widget.ImageView;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;public class ImageLoader extends Thread {    private ImageView mImageView;    private String mImageName;    private int position;    private static final String url = "http://172.46.130.144:8080/News/NewsImage/";    public ImageLoader(ImageView mImageView, String imageName, int position) {        this.mImageName = imageName;        this.mImageView = mImageView;        this.position = position;    }    Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            if (msg.what == 0) {                if (mImageView.getTag() == ImageLoader.this.position) {                    Bitmap bitmap = (Bitmap) msg.obj;                    mImageView.setImageBitmap(bitmap);                }            }        }    };    @Override    public void run() {        try {            URL url1 = new URL(url + mImageName);            HttpURLConnection urlConnection = (HttpURLConnection) url1.openConnection();            if (urlConnection.getResponseCode() == 200) {                InputStream  mIs = url1.openStream();                Bitmap bitmap = BitmapFactory.decodeStream(mIs);                this.mImageView.setTag(this.position);                handler.obtainMessage(0, bitmap).sendToTarget();            }        } catch (MalformedURLException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }    }}

6、利用BitmapCache类进行下缓存优化,代码如下

package com.kuxiao.tran.studyActivity;import android.graphics.Bitmap;import android.util.Log;import android.util.LruCache;public class BitmapCache {    private LruCache<String, Bitmap> mLruCache;    public BitmapCache() {        //获取最大运行时的最大内存        int max = (int) (Runtime.getRuntime().maxMemory() / 8);        mLruCache = new LruCache<String, Bitmap>(max) {            @Override            protected int sizeOf(String key, Bitmap value) {                //设置每一次缓存的大小                return value.getByteCount();            }        };    }    //缓存一个Bitmap对象    public void saveBitmap(String key, Bitmap value) {        mLruCache.put(key, value);    }    //取出一个Bitmap对象    public Bitmap getBitmap(String key) {        return mLruCache.get(key);    }}

四、特别说明:本人大四的小白,自学的android编程,如有不妥之处,多谢指出,服务器端的代码我就不贴出来了,有需要的朋友可以联系我QQ:953751759,Json数据生成不懂的,可以看我博客中的Json数据生成。

上述中在给ImageView设置Tag的是用的ListView中的位置,并没有用照片的URL,是因为本人服务器生成的Json数据的照片的名字相同,图片只有一张,所以Url不适合设置成Tag,大家在练习的时候注意下。

0 0
原创粉丝点击