Android照片墻的實現
實現一個簡單的照片墻。
實現原理:
1:去重復 相同的url不要下載兩次,可以用set集合對封裝的任務,但是我們應用使用了內存緩存即使不做判斷也不會加載兩次,因為LruCache對象已經幫我們實現了
2:下載圖片的任務使用了AsyncTask
3: 當我們快速滑動屏幕的時候怎么做到當手指松開的時候才加載可見屏幕范圍對應的圖片,避免了快速滑動導致卡的問題
activity_main.xml
<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=".MainActivity"><GridView android:id="@+id/photo_wall" android:layout_width="match_parent" android:layout_height="wrap_content" android:columnWidth="90dip" android:gravity="center" android:numColumns="auto_fit" android:stretchMode="columnWidth" android:verticalSpacing="10dip" /> </RelativeLayout> </pre>
Constant.javapublic class Constant {public static String[] imgs = new String[]{ "http://img5.douban.com/view/photo/thumb/public/p1042461956.jpg", "http://img5.douban.com/lpic/s28035816.jpg", "http://img3.douban.com/lpic/s28049685.jpg", "http://img5.douban.com/lpic/s28004598.jpg", "http://img5.douban.com/lpic/s28050639.jpg", "http://img3.douban.com/lpic/s28056884.jpg", "http://img5.douban.com/lpic/s28036379.jpg", "http://img5.douban.com/lpic/s28045199.jpg", "http://img3.douban.com/lpic/s28034923.jpg", "http://img5.douban.com/lpic/s28067039.jpg", "http://img3.douban.com/spic/s28000872.jpg", "http://img3.douban.com/view/movie_poster_cover/mpst/public/p2237747953.jpg", "http://img5.douban.com/view/movie_poster_cover/mpst/public/p2240110789.jpg", "http://img5.douban.com/view/movie_poster_cover/mpst/public/p2235609577.jpg", "http://img5.douban.com/view/movie_poster_cover/mpst/public/p2233113686.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2225188257.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2201518484.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2229383316.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2222477444.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2230484792.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2204911658.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2210568759.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2201468648.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2226169113.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2221319641.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2231932406.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2208286457.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2203481530.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2232079769.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2224484447.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2233767512.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2202114105.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2209761319.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2230222544.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2220776342.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2233840624.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2194199028.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2230222544.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2220776342.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2233840624.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2194199028.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2233260210.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2210832820.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2203693875.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2231791943.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2203838902.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2220218254.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2215268072.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2219669553.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2208934451.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2225669293.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2225986472.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2199678535.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2230471461.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2204888387.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2224389662.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2207808539.jpg", "http://img5.douban.com/view/movie_poster_cover/lpst/public/p2225291257.jpg", "http://img3.douban.com/view/movie_poster_cover/lpst/public/p2230505723.jpg" }; } </pre>
ImageLoaderAdapter.javapackage com.jackie.photowall;import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.util.LruCache; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashSet; import java.util.Set; /** * Created by Jackie on 5/14/15. */ public class ImageLoaderAdapter extends BaseAdapter implements AbsListView.OnScrollListener { private Activity mActivity; private GridView mGridView; private LayoutInflater mInflater; /** * 圖片緩存技術的核心類,用于緩存所有下載好的圖片,在程序內存達到設定值時會將最少最近使用的圖片移除掉。 */ private LruCache<String, Bitmap> mMemoryCache; /** * 記錄所有正在下載或等待下載的任務。 */ private Set<ImageLoaderTask> mImageLoaderTasks; /** * 第一張可見圖片的下標 */ private int mFirstVisibleItem; /** * 可見區域一屏有多少張圖片 */ private int mVisibleItemCount; /** * 代表第一次進來不滑動的時候自動加載圖片 */ private boolean mIsFirstLoader = true; public ImageLoaderAdapter(GridView mGridView, Activity mActivity) { this.mActivity = mActivity; this.mGridView = mGridView; mInflater = LayoutInflater.from(mActivity); mImageLoaderTasks = new HashSet<ImageLoaderTask>(); /** * 獲取應用給app分配的內存空間 */ int maxMemory = (int) Runtime.getRuntime().maxMemory(); /** * 給圖片分配合理的內容空間 */ int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getByteCount(); } }; mGridView.setOnScrollListener(this); } @Override public int getCount() { return Constant.imgs != null && Constant.imgs.length > 0 ? Constant.imgs.length : 0; } @Override public Object getItem(int position) { return Constant.imgs[position]; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup arg2) { final String url = (String) getItem(position); ViewHolder holder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.img_item, null); holder = new ViewHolder(); holder.imageview = (ImageView) convertView.findViewById(R.id.imageview); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } /** * 給ImageView設置一個Tag,保證異步加載圖片時不會亂序 */ holder.imageview.setTag(url); setImageView(url, holder.imageview); return convertView; } /** * 首先用url到緩存中找 如果沒有就顯示默認圖片 如果緩存中有 就顯示 * * @param url 要顯示圖片的url * @param imageview */ private void setImageView(String url, ImageView imageview) { Bitmap bitmap = mMemoryCache.get(url); if (bitmap != null && imageview != null) { imageview.setImageBitmap(bitmap); } else { // imageview.setImageResource(R.drawable.empty_photo); } } class ViewHolder { ImageView imageview; } /** * view 就是GridView * firstVisibleItem 可見 第一個條目 * visibleItemCount 可見的總條目 * totalItemCount 要加載的總條目 */ @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { mFirstVisibleItem = firstVisibleItem; mVisibleItemCount = visibleItemCount; if (mIsFirstLoader && visibleItemCount > 0) { loadImages(firstVisibleItem, visibleItemCount); mIsFirstLoader = false; } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // 僅當GridView靜止時才去下載圖片,GridView滑動時取消所有正在下載的任務 if (scrollState == SCROLL_STATE_IDLE) { loadImages(mFirstVisibleItem, mVisibleItemCount); } else { cancelAllTasks(); } } private void cancelAllTasks() { if (mImageLoaderTasks != null) { for (ImageLoaderTask task : mImageLoaderTasks) { task.cancel(false); } } } private void loadImages(int firstVisibleItem, int visibleItemCount) { for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) { String imagUrl = Constant.imgs[i]; Bitmap bitmap = getBitmapFromMemory(imagUrl); if (bitmap == null) {//從網絡獲取 ImageLoaderTask task = new ImageLoaderTask(); mImageLoaderTasks.add(task); task.execute(imagUrl); } else {//從緩存獲取 ImageView imageView = (ImageView) mGridView.findViewWithTag(imagUrl); if (imageView != null && bitmap != null) { imageView.setImageBitmap(bitmap); } } } } private Bitmap getBitmapFromMemory(String key) { return mMemoryCache.get(key); } private class ImageLoaderTask extends AsyncTask<String, Void, Bitmap> { String url = null; @Override protected Bitmap doInBackground(String... param) { url = param[0]; /** * 從網絡上加載的圖片 如果bitmap不為null 就加載到內存之中 */ Bitmap bitmap = downLoadImage(url); if (bitmap != null) { // 圖片下載完成后緩存到LrcCache中 addBitmapToMemoryCache(url, bitmap); } return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); ImageView imageView = (ImageView) mGridView.findViewWithTag(url); if (imageView != null && bitmap != null) { imageView.setImageBitmap(bitmap); } /** * 下載完了以后把該任務從集合中移除 可能有些人會說為什么要用hashset集合 因為他可以的任務不重復 */ mImageLoaderTasks.remove(this); } } public Bitmap downLoadImage(String imgUrl) { Bitmap bitmap = null; HttpURLConnection connection = null; try { URL url = new URL(imgUrl); connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(5 * 1000); connection.setReadTimeout(10 * 1000); connection.setDoInput(true); bitmap = BitmapFactory.decodeStream(connection.getInputStream()); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (connection != null) { connection.disconnect(); } } return bitmap; } /** * 把圖片加載到內存之中 * * @param url 圖片的url * @param bitmap url對應的圖片 */ public void addBitmapToMemoryCache(String url, Bitmap bitmap) { if (getBitmapFromMemory(url) == null) { mMemoryCache.put(url, bitmap); } } } </pre>
效果圖:
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!