android非同步載入

來源:互聯網
上載者:User

標籤:

轉載請說明出處,歡迎轉載。http://write.blog.csdn.net/postedit/51533261

本篇部落格總結了慕課網關於非同步載入圖片的知識要點,和大家一起分享,有感覺聽得不連貫的可以來看看。

看完本篇部落格,你將學習到下面的知識:

1.怎樣將一個url(也可以說是一個InputStream)轉換為一個json字串資訊。

2.怎樣運用外掛程式寫一個我認為完美的model類來為解析json做準備。

3.AsyncTask的基本用法。

4.Gosn的基本用法。

5.Adapter的常用最佳化寫法。

6.通過LruCache緩衝已經載入的圖片。

7.listview高效載入複雜item布局。

8.編寫json實體類的AS小外掛程式。

好了,直接上代碼,代碼裡面有詳細的解釋。

package com.robin.loadimageinlistview;import android.os.AsyncTask;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.widget.ListView;import com.google.gson.Gson;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.URL;import java.util.List;public class MainActivity extends AppCompatActivity {    private ListView listView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        listView = (ListView) findViewById(R.id.lv_main);        String URL1 = "http://www.imooc.com/api/teacher?type=4&num=30";        new MyAsyncTask().execute(URL1);    }    class MyAsyncTask extends AsyncTask<String, Void, List<NewsBean.BeanData>> {//<strong><span style="color:#ff0000;">(知識點3)</span></strong>        @Override        protected List<NewsBean.BeanData> doInBackground(String... params) {            return getJsonData(params[0]);        }        @Override        protected void onPostExecute(List<NewsBean.BeanData> beanDatas) {            super.onPostExecute(beanDatas);            NewsAdapter adapter = new NewsAdapter(MainActivity.this, beanDatas, listView);            listView.setAdapter(adapter);        }    }    /**     * 通過URL擷取json字串<strong><span style="color:#ff0000;">(知識點2)</span></strong>     *     * @param url     * @return List<NewsBean.BeanData>     */    private List<NewsBean.BeanData> getJsonData(String url) {        String jsonString = null;        try {            jsonString = readStream(new URL(url).openStream());        } catch (IOException e) {            e.printStackTrace();        }        Gson gson = new Gson();        if(jsonString==null||"".equals(jsonString))return null;//如果jsonString返回有問題,就不解析了。        NewsBean newsBean = gson.fromJson(jsonString, NewsBean.class);//<span style="color:#ff0000;"><strong>(知識點4)</strong></span>需要將Gosn的包匯入進project中。怎麼導,就不詳細說了,去Google        return newsBean.getData();    }    /**     * 怎樣將一個url(也可以說是一個InputStream)轉換為一個json字串資訊。<strong><span style="color:#ff0000;">(知識點1)</span></strong>     *     * @param is     * @return String     */    private String readStream(InputStream is) {        String result = "";        InputStreamReader isr;        String line;        try {            isr = new InputStreamReader(is, "utf-8");//位元組流轉化為字元流            BufferedReader br = new BufferedReader(isr);            while ((line = br.readLine()) != null) {                result += line;            }        } catch (IOException e) {            e.printStackTrace();        }        return result;    }}

接下來開始放Adapter (知識點5)

package com.robin.loadimageinlistview;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AbsListView;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.ListView;import android.widget.TextView;import java.util.List;public class NewsAdapter extends BaseAdapter implements AbsListView.OnScrollListener{    private List<NewsBean.BeanData> newsBeans;    private LayoutInflater mInflater;    private ImageLoader imageLoader;    private int mStart,mEnd;    public static String[] URLS;//存放要載入的圖片的url    private boolean isFirst = false;//控制第一次進入listview的時候載入資料    public NewsAdapter(Context context, List<NewsBean.BeanData> newsBeans, ListView listView) {//初始化資料        this.newsBeans = newsBeans;        this.mInflater = LayoutInflater.from(context);        imageLoader = new ImageLoader(listView);// 確保只有一個LruCache                URLS = new String[newsBeans.size()];        for (int i=0;i<newsBeans.size();i++){//擷取newsBeans中的圖片的url            URLS[i] = newsBeans.get(i).getPicSmall();                    }        isFirst = true;        listView.setOnScrollListener(this);    }    @Override    public int getCount() {        return newsBeans.size();    }    @Override    public Object getItem(int position) {        return newsBeans.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        ViewHolder viewHolder;//利用viewholder進行最佳化,這一點也是寫類似listview的adapter的getView方法的一個模板。        if(convertView==null){            viewHolder = new ViewHolder();            convertView = mInflater.inflate(R.layout.item_layout,null);            viewHolder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon);            viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);            viewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);            convertView.setTag(viewHolder);        }else{//如果convertView不為空白就不用再次去載入布局了,因為載入布局耗時很長,造成listview的卡頓            viewHolder = (ViewHolder) convertView.getTag();        }        viewHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);        String url = newsBeans.get(position).getPicSmall();        viewHolder.ivIcon.setTag(url);//將url作為tag        imageLoader.showImageByAsyncTask(viewHolder.ivIcon,url);        viewHolder.tvTitle.setText(newsBeans.get(position).getName());        viewHolder.tvContent.setText(newsBeans.get(position).getDescription());        return convertView;    }    @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {//滑動狀態改變時調用<span style="color:#ff0000;"><strong>(知識點7)</strong></span>        if(scrollState==SCROLL_STATE_IDLE){//停止滾動,載入可見項            imageLoader.loadImage(mStart,mEnd);        }else{//停止載入            imageLoader.cancelAllTask();        }    }    @Override    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {//整個滑動的時候都會調用        mStart = firstVisibleItem;//第一個可見元素        mEnd =firstVisibleItem+visibleItemCount;//最後一個可見元素=第一個可見元素+可見元素的數量        if(isFirst && visibleItemCount > 0){//第一次載入的時候調用,顯示圖片            imageLoader.loadImage(mStart,mEnd);            isFirst=false;        }    }    class ViewHolder{        public TextView tvTitle;        public TextView tvContent;        public ImageView ivIcon;    }}
  對 知識點7的一點解釋,當item布局非常複雜的時候,這是使用者區頻繁滾動listview,listview會頻繁調用getView方法去擷取item,導致卡頓,然而,平常的使用過程中,我們發現一般使用者滾動的時候不太注意內容,停止滾動的時候才回去看內容,因此我們考慮如果將顯示內容的權利從getView中移交給滾動事件處理的話,這個問題就能得到解決。

接下來上最重要的控製圖片緩衝以及載入的類

package com.robin.loadimageinlistview;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.AsyncTask;import android.util.LruCache;import android.widget.ImageView;import android.widget.ListView;import java.io.BufferedInputStream;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import java.util.HashSet;import java.util.Set;public class ImageLoader {        private LruCache<String,Bitmap> cache;//用於緩衝圖片    private ListView listView;    private Set<NewsAsyncTask> mTask;//管理AsyncTask    public ImageLoader(ListView listView) {//初始化一些資料        this.listView = listView;        this.mTask = new HashSet<>();        int maxMemry = (int) Runtime.getRuntime().maxMemory();//擷取當前應用可用的最大記憶體        int cacheSize = maxMemry/4;//以最大的四分之一作為可用的緩衝大小        this.cache = new LruCache<String,Bitmap>(cacheSize){//初始化LruCache            @Override            protected int sizeOf(String key, Bitmap value) {                return value.getByteCount();//每次存入緩衝的大小,即bitmap的大小            }        };            }    /**     * 將內容儲存到LruCache     * @param url     * @param bitmap     */    public void addBitmapToCache(String url,Bitmap bitmap){        if(getBitmapFromCache(url)==null){//如果沒有儲存的話就儲存。                cache.put(url,bitmap);        }    }    /**     * 從LruCache中擷取bitmap     * @param url     * @return Bitmap     */    public Bitmap getBitmapFromCache(String url){     return this.cache.get(url);       }    /**     * 將圖片url轉化為bitmap     * @param urlString     * @return Bitmap     */    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();            return bitmap;        } catch (IOException e) {            e.printStackTrace();        }finally {            try {                if(is!=null){                    is.close();                }            } catch (IOException e) {                e.printStackTrace();            }        }        return null;    }        public void showImageByAsyncTask(ImageView imageView,String url){//改進之後,擷取圖片的控制權由原來getview改成了滾動狀態。        Bitmap bitmap = getBitmapFromCache(url);//從緩衝中擷取圖片        if(bitmap==null){//如果沒有就設定預設的圖片            imageView.setImageResource(R.mipmap.ic_launcher);        }else{//如果有就設定當前的圖片            imageView.setImageBitmap(bitmap);        }           }        private class NewsAsyncTask extends AsyncTask<String,Void,Bitmap>{        private String url;        public NewsAsyncTask(String url) {            this.url = 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) listView.findViewWithTag(url);            if(imageView!=null&&bitmap!=null){//判斷這個url所對應的imageview是否對應,對應的話才設定圖片,                 imageView.setImageBitmap(bitmap);            }                    }    }    /**     * 載入從start到end的所有圖片     * @param start     * @param end     */    public void loadImage(int start,int end){        for (int i= start;i<end;i++){//拿到數組中的圖片對應的url            String url = NewsAdapter.URLS[i];            Bitmap bitmap = getBitmapFromCache(url);            if(bitmap==null){//沒有就要去下載                NewsAsyncTask newsAsyncTask = new NewsAsyncTask(url);                newsAsyncTask.execute(url);                mTask.add(newsAsyncTask);            }else{                ImageView imageView =(ImageView) listView.findViewWithTag(url);//通過findViewWithTag找到imageview,這個tag就是imageview的url                imageView.setImageBitmap(bitmap);            }        }    }    public void cancelAllTask() {        if(mTask!=null){            for (NewsAsyncTask task:mTask) {                task.cancel(false);            }        }    }}

最後送上一個小外掛程式 (知識點8),只恨自己執導的太晚,要是有個這個神奇,實體類就不在這麼難寫了。再次分享給大家,尤其是企業開發的時候,經常能用到,上 git地址,包括用法,安裝很詳細的。

https://github.com/zzz40500/GsonFormat

好了,大概就這些了,上傳一張


最後感謝大家,喜歡請點贊,有疑問,可以回複交流,有錯誤,請指出。Thx。

轉載請說明出處,歡迎轉載。http://write.blog.csdn.net/postedit/51533261

阿斯頓

android非同步載入

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.