Givemepass's Android 惡補筆記

如何使用ThreadPool 來下載網路圖片

| Comments

在之前如何從網路下載圖片的文章是下載一張圖片,

那如果要在listview內下載圖片,

又不想要影響滑動怎麼辦呢?

在網路圖片還沒下載好之前, 就先用預設圖片來裝一下就好。

可以自由滑動直到網路圖片下載完畢再更新。

根據如何從網路下載圖片的程式碼修改

public void handleWebPic(final String url, final int index){
        
        ThreadPoolManager.getInstance().addSelectPhotoTask(
            new Thread(new Runnable(){
                @Override
                public void run() {
                    
                    Bitmap bmp = getUrlPic(url);
                    bmpList.add(index, bmp);
                    runOnUiThread(new Runnable(){

                        @Override
                        public void run() {
                            
                            if(mMyAdapter != null){
                                mMyAdapter.notifyDataSetChanged();
                            }
                        }
                        
                    });
                            
                            
                        
                    
                } 
            })
        );
    }
    
    public synchronized Bitmap getUrlPic(String url) {
        
        Bitmap webImg = null;
          
        try {
            URL imgUrl = new URL(url);
            HttpURLConnection httpURLConnection 
                    = (HttpURLConnection) imgUrl.openConnection();
            httpURLConnection.connect();
            InputStream inputStream = httpURLConnection.getInputStream();
            int length = (int) httpURLConnection.getContentLength();
            int tmpLength = 512;
            int readLen = 0,desPos = 0;
            byte[] img = new byte[length];
            byte[] tmp = new byte[tmpLength];
            if (length != -1) {
                while ((readLen = inputStream.read(tmp)) > 0) {
                    System.arraycopy(tmp, 0, img, desPos, readLen);
                    desPos += readLen;
                }
                webImg = BitmapFactory.decodeByteArray(img, 0,img.length);
                if(desPos != length){
                    throw new IOException("Only read" + desPos +"bytes");
                }
            }
            httpURLConnection.disconnect();
        }
        catch (IOException e) {
            Log.e("IOException",e.toString());
        }
        return webImg;
    }

當抓完網路圖片以後, 則丟到一個圖片陣列內

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = getApplicationContext();
        mListView = (ListView) findViewById(R.id.listview);
        bmpList = new ArrayList<Bitmap>();
        for(int i = 0; i < 100; i++){
            bmpList.add(null);
            handleWebPic("http://uploadingit.com/file/lltpirkd9pk3jbuw/raccoon.png", i);
        }
        
        
        mMyAdapter = new MyAdapter();
        mListView.setAdapter(mMyAdapter);
        
    }

一開始宣告一個listview 跟 adapter, 然後假設我們要抓一百張圖片,
因為我懶所以抓同一張, 不影響結果。

那如果他一開始還沒有圖片, 就讓這個bitmap為null。

private class MyAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            // TODO Auto-generated method stub

            return bmpList.size();
        }

        @Override
        public Object getItem(int arg0) {
            // TODO Auto-generated method stub

            return null;
        }

        @Override
        public long getItemId(int arg0) {
            // TODO Auto-generated method stub

            return 0;
        }

        @Override
        public View getView(int position, View view, ViewGroup arg2) {
            View v = view;
            Holder holder;
            if(v == null){
                v = LayoutInflater.from(mContext).inflate(R.layout.listview_item, null);
                holder = new Holder();
                holder.img = (ImageView) v.findViewById(R.id.img);
                v.setTag(holder);
            } else{
                holder = (Holder) v.getTag();
            }
            if(bmpList.get(position) == null){
                holder.img.setImageResource(R.drawable.ic_launcher);
            } else{
                holder.img.setImageBitmap(bmpList.get(position));
            }
            return v;
        }
        class Holder{
            ImageView img;
        }
    }

關鍵字就是圖片為null的時候, 表示還沒下載完, 所以就讓他為預設圖片,
否則就刷新呈現出來。

至於thradpool要怎麼使用呢?

public class ThreadPoolManager {

    private static ThreadPoolManager mThreadPoolManager;
    
    private final int KEEP_ALIVE_TIME = 3;
    // Sets the Time Unit to seconds

    private final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
    // Creates a thread pool manager

    
    private ThreadPoolManager(){}
    
    public static ThreadPoolManager getInstance(){
        if(null == mThreadPoolManager){
            mThreadPoolManager = new ThreadPoolManager();
        }
        return mThreadPoolManager;
    }
    
    private final BlockingQueue<Runnable> mPhotoQueue = new LinkedBlockingQueue<Runnable>();
    
    private ThreadPoolExecutor mPhotoExcutor = new ThreadPoolExecutor(
            4,       // Initial pool size

            5,       // Max pool size

            KEEP_ALIVE_TIME,
            KEEP_ALIVE_TIME_UNIT,
            mPhotoQueue);
    
    public void addSelectPhotoTask(Runnable runnable){
        mPhotoExcutor.execute(runnable);
    }
}

寫一個獨體模式 讓他去跑thread 利用內建的排程LinkedBlockingQueue (還有很多種)
讓他用佇列一個一個跑完以後, 就對畫面做更新。

這樣就完成一個簡單的排程。

程式碼
http://uploadingit.com/file/grnmbj4buiulhcdv/ThreadPoolDemo.zip

Comments

comments powered by Disqus