Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android異步加載

android異步加載

編輯:關於Android編程

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

看完本篇博客,你將學習到下面的知識:

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> {//(知識點3)

        @Override
        protected List doInBackground(String... params) {
            return getJsonData(params[0]);
        }

        @Override
        protected void onPostExecute(List beanDatas) {
            super.onPostExecute(beanDatas);
            NewsAdapter adapter = new NewsAdapter(MainActivity.this, beanDatas, listView);
            listView.setAdapter(adapter);
        }
    }

    /**
     * 通過URL獲取json字符串(知識點2)
     *
     * @param url
     * @return List
     */
    private List 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);//(知識點4)需要將Gosn的包導入進project中。怎麼導,就不詳細說了,去Google
        return newsBean.getData();
    }

    /**
     * 怎樣將一個url(也可以說是一個InputStream)轉換為一個json字符串信息。(知識點1)
     *
     * @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 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 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(知識點7)
        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 cache;//用於緩存圖片
    private ListView listView;
    private Set 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(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{
        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

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

https://github.com/zzz40500/GsonFormat

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

\

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved