1.三级缓存的代码。
public class PhotoWallAdapter extends BaseAdapter implements OnScrollListener {
private List<Costume> listCostumes;
private Activity mActivity;
private String path;
/**
* 记录所有正在下载或等待下载的任务。
*/
private Set<BitmapWorkerTask> taskCollection;
/**
* 图片缓存技术的核心类,用于缓存所有下载好的图片,在程序内存达到设定值时会将最少最近使用的图片移除掉。
*/
private LruCache<String, Bitmap> mMemoryCache;
/**
* GridView的实例
*/
private GridView mPhotoWall;
/**
* 第一张可见图片的下标
*/
private int mFirstVisibleItem;
/**
* 一屏有多少张图片可见
*/
private int mVisibleItemCount;
/**
* 记录是否刚打开程序,用于解决进入程序不滚动屏幕,不会下载图片的问题。
*/
private boolean isFirstEnter = true;
@SuppressLint("NewApi")
public PhotoWallAdapter(Activity mActivity,List<Costume> listCostume,String path,
GridView photoWall) {
this.mActivity=mActivity;
this.mPhotoWall = photoWall;
this.listCostumes=listCostume;
this.path=path;
taskCollection = new HashSet<BitmapWorkerTask>();
// 获取应用程序最大可用内存
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 8;
// 设置图片缓存大小为程序最大可用内存的1/8
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@SuppressLint("NewApi")
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getByteCount();
}
};
this.mPhotoWall.setOnScrollListener(this);
}
public void initData(List<Costume> listCostume){
this.listCostumes=listCostume;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder=null;
if(convertView==null){
viewHolder=new ViewHolder();
convertView=LayoutInflater.from(mActivity).inflate(R.layout.item,null);
viewHolder.detail=(TextView) convertView.findViewById(R.id.grid_tv_detail);
viewHolder.dollar=(TextView) convertView.findViewById(R.id.grid_tv_dollar);
viewHolder.iv=(ImageView) convertView.findViewById(R.id.iv_gridId);
convertView.setTag(viewHolder);
}else{
viewHolder=(ViewHolder) convertView.getTag();
}
viewHolder.detail.setText("【超值惠】"+listCostumes.get(position).getDetail());
viewHolder.dollar.setText("$"+listCostumes.get(position).getPrice());
String imagePath=listCostumes.get(position).getImageUrl();
viewHolder.iv.setImageResource(R.drawable.ic_launcher);
// 给ImageView设置一个Tag,保证异步加载图片时不会乱序
viewHolder.iv.setTag(imagePath);
setImageView(imagePath,viewHolder.iv);
return convertView;
}
/**
* 给ImageView设置图片。首先从LruCache中取出图片的缓存,设置到ImageView上。如果LruCache中没有该图片的缓存,
* 就给ImageView设置一张默认图片。
*
* @param imageUrl
* 图片的URL地址,用于作为LruCache的键。
* @param imageView
* 用于显示图片的控件。
*/
private void setImageView(String imageUrl, ImageView imageView) {
Bitmap bitmapCache = getBitmapFromMemoryCache(imageUrl);
if (bitmapCache != null) {
imageView.setImageBitmap(bitmapCache);
}else {
imageView.setImageResource(R.drawable.empty_photo);
}
}
/**
* 将一张图片存储到LruCache中。
*
* @param key
* LruCache的键,这里传入图片的URL地址。
* @param bitmap
* LruCache的键,这里传入从网络上下载的Bitmap对象。
*/
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemoryCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}
/**
* 从LruCache中获取一张图片,如果不存在就返回null。
*
* @param key
* LruCache的键,这里传入图片的URL地址。
* @return 对应传入键的Bitmap对象,或者null。
*/
public Bitmap getBitmapFromMemoryCache(String key) {
return mMemoryCache.get(key);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 仅当GridView静止时才去下载图片,GridView滑动时取消所有正在下载的任务
if (scrollState == SCROLL_STATE_IDLE) {
loadBitmaps(mFirstVisibleItem, mVisibleItemCount);
} else {
cancelAllTasks();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
mFirstVisibleItem = firstVisibleItem;
mVisibleItemCount = visibleItemCount;
// 下载的任务应该由onScrollStateChanged里调用,但首次进入程序时onScrollStateChanged并不会调用,
// 因此在这里为首次进入程序开启下载任务。
if (isFirstEnter && visibleItemCount > 0) {
loadBitmaps(firstVisibleItem, visibleItemCount);
isFirstEnter = false;
}
}
/**
* 加载Bitmap对象。此方法会在LruCache中检查所有屏幕中可见的ImageView的Bitmap对象,
* 如果发现任何一个ImageView的Bitmap对象不在缓存中,就会开启异步线程去下载图片。
*
* @param firstVisibleItem
* 第一个可见的ImageView的下标
* @param visibleItemCount
* 屏幕中总共可见的元素数
*/
private void loadBitmaps(int firstVisibleItem, int visibleItemCount) {
try {
for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) {
String imageUrl =listCostumes.get(i).getImageUrl();
Bitmap bitmap = getBitmapFromMemoryCache(imageUrl);
ImageView imageView = (ImageView) mPhotoWall.findViewWithTag(imageUrl);
if (bitmap == null) {
String imageName = "";
if (imageUrl != null) {
imageName = Util.getInstance().getImageName(imageUrl);
}
if(imageView != null && imageUrl.equals(imageView.getTag())) {
Bitmap bitmapfile = getBitmapFromFile(mActivity, imageName, path);
if (bitmapfile != null) {
imageView.setImageBitmap(bitmapfile);
}else{
BitmapWorkerTask task = new BitmapWorkerTask();
taskCollection.add(task);
task.execute(imageUrl);
}
}
} else {
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 取消所有正在下载或等待下载的任务。
*/
public void cancelAllTasks() {
if (taskCollection != null) {
for (BitmapWorkerTask task : taskCollection) {
task.cancel(false);
}
}
}
/**
* 异步下载图片的任务。
*
* @author guolin
*/
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
/**
* 图片的URL地址
*/
private String imageUrl;
@Override
protected Bitmap doInBackground(String... params) {
imageUrl = params[0];
// 在后台开始下载图片
Bitmap bitmap = downloadBitmap(params[0]);
if (bitmap != null) {
String imageName = Util.getInstance().getImageName(imageUrl);
if(!setBitmapToFile(path,mActivity,imageName,bitmap)){
removeBitmapFromFile(imageName, mActivity, imageName);
}
// 图片下载完成后缓存到LrcCache中
addBitmapToMemoryCache(params[0], bitmap);
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
// 根据Tag找到相应的ImageView控件,将下载好的图片显示出来。
ImageView imageView = (ImageView) mPhotoWall.findViewWithTag(imageUrl);
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
taskCollection.remove(this);
}
/**
* 建立HTTP请求,并获取Bitmap对象。
*
* @param imageUrl
* 图片的URL地址
* @return 解析后的Bitmap对象
*/
private Bitmap downloadBitmap(String imageUrl) {
Bitmap bitmap = null;
HttpURLConnection con = null;
try {
URL c_url = new URL(imageUrl);
InputStream bitmap_data = c_url.openStream();
bitmap = BitmapFactory.decodeStream(bitmap_data);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (con != null) {
con.disconnect();
}
}
return bitmap;
}
}
public class ViewHolder{
ImageView iv;
TextView detail;
TextView dollar;
}
@Override
public int getCount() {
return listCostumes.size();
}
@Override
public Object getItem(int arg0) {
return listCostumes.get(arg0);
}
@Override
public long getItemId(int arg0) {
return arg0;
}
/**
* 从文件中拿图片
* @param mActivity
* @param imageName 图片名字
* @param path 图片路径
* @return
*/
private Bitmap getBitmapFromFile(Activity mActivity,String imageName,String path){
Bitmap bitmap = null;
if(imageName != null){
File file = null;
String real_path = "";
try {
if(Util.getInstance().hasSDCard()){
real_path = Util.getInstance().getExtPath() + (path != null && path.startsWith("/") ? path : "/" + path);
}else{
real_path = Util.getInstance().getPackagePath(mActivity) + (path != null && path.startsWith("/") ? path : "/" + path);
}
file = new File(real_path, imageName);
if(file.exists())
bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
} catch (Exception e) {
e.printStackTrace();
bitmap = null;
}
}
return bitmap;
}
/**
* 将下载好的图片存放到文件中
* @param path 图片路径
* @param mActivity
* @param imageName 图片名字
* @param bitmap 图片
* @return
*/
private boolean setBitmapToFile(String path,Activity mActivity,String imageName,Bitmap bitmap){
File file = null;
String real_path = "";
try {
if(Util.getInstance().hasSDCard()){
real_path = Util.getInstance().getExtPath() + (path != null && path.startsWith("/") ? path : "/" + path);
}else{
real_path = Util.getInstance().getPackagePath(mActivity) + (path != null && path.startsWith("/") ? path : "/" + path);
}
file = new File(real_path, imageName);
if(!file.exists()){
File file2 = new File(real_path + "/");
file2.mkdirs();
}
file.createNewFile();
FileOutputStream fos = null;
if(Util.getInstance().hasSDCard()){
fos = new FileOutputStream(file);
}else{
fos = mActivity.openFileOutput(imageName, Context.MODE_PRIVATE);
}
if (imageName != null && (imageName.contains(".png") || imageName.contains(".PNG"))){
bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
}
else{
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
}
fos.flush();
if(fos != null){
fos.close();
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 辅助方法,一般不调用
* @param path
* @param mActivity
* @param imageName
*/
private void removeBitmapFromFile(String path,Activity mActivity,String imageName){
File file = null;
String real_path = "";
try {
if(Util.getInstance().hasSDCard()){
real_path = Util.getInstance().getExtPath() + (path != null && path.startsWith("/") ? path : "/" + path);
}else{
real_path = Util.getInstance().getPackagePath(mActivity) + (path != null && path.startsWith("/") ? path : "/" + path);
}
file = new File(real_path, imageName);
if(file != null)
file.delete();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.自定义的PagerAdapter的
public class FragmentViewPagerAdapter extends PagerAdapter implements
OnPageChangeListener {
private List<Fragment> listFragments;
private FragmentManager fragmentmanager;
private ViewPager viewPagr;
private int currentIndex=0;
private OnExtraPageChangeListener mOnExtraPageChangeListener;
public FragmentViewPagerAdapter(FragmentManager fragmentmanager,List<Fragment> listFragments,ViewPager viewpager){
this.fragmentmanager=fragmentmanager;
this.listFragments=listFragments;
this.viewPagr=viewpager;
this.viewPagr.setAdapter(this);
this.viewPagr.setOffscreenPageLimit(0);
this.viewPagr.setOnPageChangeListener(this);
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageSelected(int pageindex) {
listFragments.get(currentIndex).onPause();
if(listFragments.get(pageindex).isAdded()){
listFragments.get(pageindex).onResume();
}
currentIndex=pageindex;
if(null!=mOnExtraPageChangeListener){
mOnExtraPageChangeListener.onExtraPageSelected(pageindex);
}
}
@Override
public int getCount() {
return listFragments.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0==arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(listFragments.get(position).getView());
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fg=listFragments.get(position);
if(!fg.isAdded()){
android.support.v4.app.FragmentTransaction ft=fragmentmanager.beginTransaction();
ft.add(fg,ft.getClass().getSimpleName());
ft.commit();
fragmentmanager.executePendingTransactions();
}
if(fg.getView().getParent()==null){
container.addView(fg.getView());
}
return fg.getView();
}
public interface OnExtraPageChangeListener{
public void onExtraPageScrolled(int i, float v, int i2);
public void onExtraPageSelected(int i);
public void onExtraPageScrollStateChanged(int i);
}
public OnExtraPageChangeListener getmOnExtraPageChangeListener() {
return mOnExtraPageChangeListener;
}
public void setmOnExtraPageChangeListener(
OnExtraPageChangeListener mOnExtraPageChangeListener) {
this.mOnExtraPageChangeListener = mOnExtraPageChangeListener;
}
}
3.这是一个FragmentHot
public class FragmentHot extends Fragment {
private ProgressDialog progress;
private List<Costume> list=new ArrayList<Costume>();
private PullToRefreshGridView RefresGridView;
private GridView mGridView;
//private GridAdapter adapter=null;
private PhotoWallAdapter mPhotoWallAdapter;
private int pageindex=1;
private Downinfo mDowninfo=null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.grid_item,container,false);
RefresGridView=(PullToRefreshGridView) view.findViewById(R.id.grid_address);
mGridView=RefresGridView.getRefreshableView();
//adapter=new GridAdapter(list,getActivity(),mGridView,"textGridview");
mPhotoWallAdapter=new PhotoWallAdapter(getActivity(),list,"textjjr",mGridView);
progress=new ProgressDialog(getActivity());
progress.setTitle("温馨提示");
progress.setMessage("正在努力加载....");
progress.show();
mGridView.setAdapter(mPhotoWallAdapter);
mDowninfo=new Downinfo();
mDowninfo.start();
RefresGridView.setOnRefreshListener(new OnRefreshListener2<GridView>() {
@Override
public void onPullDownToRefresh(PullToRefreshBase<GridView> refreshView) {
RefresGridView.onRefreshComplete();
}
@Override
public void onPullUpToRefresh(PullToRefreshBase<GridView> refreshView) {
pageindex++;
Downinfo f=new Downinfo();
f.start();
}
});
return view;
}
public class Downinfo extends Thread{
@Override
public void run() {
String result=HttpUtils.getString(CommUtils.HOTPANT_PATH+pageindex);
list.addAll(HttpUtils.getData(result));
handler.post(new Runnable() {
@Override
public void run() {
mPhotoWallAdapter.initData(list);
mPhotoWallAdapter.notifyDataSetChanged();
RefresGridView.onRefreshComplete();
progress.dismiss();
}
});
}
}
public Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
};
};
@Override
public void onResume() {
super.onResume();
}
@Override
public void onPause() {
super.onPause();
if(mDowninfo!=null){
mDowninfo.interrupt();
}
}
}
4.MainActivity
public class MainActivity extends FragmentActivity {
private TextView tv1,tv2,tv3,tv4;
private ViewPager viewPager;
private List<Fragment> pageViews;
private List<TextView> tvs=new ArrayList<TextView>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initWidget();
FragmentViewPagerAdapter fviewPagerAdapter=new FragmentViewPagerAdapter(getSupportFragmentManager(),pageViews,viewPager);
fviewPagerAdapter.setmOnExtraPageChangeListener(new OnExtraPageChangeListener() {
@Override
public void onExtraPageSelected(int i) {
if(i==1){
FragmentJeans j=(FragmentJeans) pageViews.get(i);
j.LoadData();
}else if(i==2){
FragmentLeggings l=(FragmentLeggings) pageViews.get(i);
l.LoadData();
}else if(i==3){
FragmentRela r=(FragmentRela) pageViews.get(i);
r.LoadData();
}
}
@Override
public void onExtraPageScrolled(int i, float v, int i2) {
// TODO Auto-generated method stub
}
@Override
public void onExtraPageScrollStateChanged(int i) {
// TODO Auto-generated method stub
}
});
}
public void initWidget(){
tv1=(TextView) findViewById(R.id.tv1_paint_title);
tv2=(TextView) findViewById(R.id.tv2_paint_title);
tv3=(TextView) findViewById(R.id.tv3_paint_title);
tv4=(TextView) findViewById(R.id.tv4_paint_title);
viewPager=(ViewPager) findViewById(R.id.vp_pant);
pageViews=new ArrayList<Fragment>();
FragmentHot fHot=new FragmentHot();
FragmentJeans fJeans=new FragmentJeans();
FragmentLeggings fLeggings=new FragmentLeggings();
FragmentRela fRela=new FragmentRela();
pageViews.add(fHot);
pageViews.add(fJeans);
pageViews.add(fLeggings);
pageViews.add(fRela);
}
}
5.布局文件中使用到第三方的类库(是GridView的下拉刷新)不再提供
<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"
tools:context=".MainActivity" >
<LinearLayout
android:id="@+id/linearTitle"
android:layout_width="match_parent"
android:layout_height="35dp"
android:gravity="center"
android:orientation="horizontal"
>
<TextView
android:id="@+id/tv1_paint_title"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#ee0e65"
android:gravity="center"
android:text="热裤"
/>
<TextView
android:id="@+id/tv2_paint_title"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="打底裤"
/>
<TextView
android:id="@+id/tv3_paint_title"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="休闲裤"
/>
<TextView
android:id="@+id/tv4_paint_title"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="牛仔裤"
/>
</LinearLayout>
<android.support.v4.view.ViewPager
android:id="@+id/vp_pant"
android:layout_below="@id/linearTitle"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</android.support.v4.view.ViewPager>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.handmark.pulltorefresh.library.PullToRefreshGridView
xmlns:ptr="http://schemas.android.com/apk/res-auto"
android:id="@+id/grid_address"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:numColumns="2"
android:verticalSpacing="1dp"
android:horizontalSpacing="1dp"
android:columnWidth="100dp"
android:stretchMode="columnWidth"
android:gravity="fill"
ptr:ptrMode="both"
ptr:ptrDrawable="@drawable/default_ptr_rotate" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/iv_gridId"
android:layout_width="100sp"
android:layout_height="100sp"
android:scaleType="fitXY"
android:layout_marginLeft="10sp"
android:src="@drawable/ic_launcher"
/>
<TextView
android:id="@+id/grid_tv_detail"
android:layout_width="100sp"
android:layout_height="wrap_content"
android:textSize="12sp"
android:text="超值惠"
android:lines="2"
android:ellipsize="end"
/>
<TextView
android:id="@+id/grid_tv_dollar"
android:layout_width="100sp"
android:layout_height="25sp"
android:textColor="#fd6185"
android:textSize="15sp"
android:text="$ 298"
/>
</LinearLayout>