1 /** 2 * @author CHQ 3 * @version 1.0 4 * @date 創建時間: 2016/7/26 17:18 5 * @parameter 6 * @return 7 * 圖片查看器 8 * //可以查看網絡圖片 9 * //可以查看本地圖片 10 */ 11 public class PhotoScan extends Activity { 12 private PhotoViewPager mViewPager; 13 private List<View> mViews; 14 private List<String> mPics; 15 private int index; 16 17 private ImageView mImageView; //當前圖片 18 private PhotoViewAttacher mAttacher; //圖片放大縮小查看 19 20 private TextView tv_hint01; 21 private TextView tv_hint02; 22 private int imageType = 0; //判斷圖片瀏覽器查看的圖片類型:0.網絡圖片 1.本地圖片 23 private LruCache<String,Bitmap> mLruCache; 24 private int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 25 26 @Override 27 protected void onCreate(Bundle savedInstanceState) { 28 super.onCreate(savedInstanceState); 29 setContentView(R.layout.activity_picture_view); 30 init(); 31 setEvent(); 32 } 33 34 private void init() { 35 MyApplication.getInstance().addActivity("PhotoScan",PhotoScan.this); 36 index = getIntent().getIntExtra("index",0); 37 imageType = getIntent().getIntExtra("imageType",0); 38 mViewPager = (PhotoViewPager) findViewById(R.id.viewPager); 39 mLruCache = new LruCache<>(maxMemory/8); 40 tv_hint01 = (TextView) findViewById(R.id.tv_hint01); 41 tv_hint02 = (TextView) findViewById(R.id.tv_hint02); 42 43 mPics = getIntent().getStringArrayListExtra("pics"); 44 tv_hint02.setText(" /"+mPics.size()); 45 mViews = new ArrayList<>(); 46 LayoutInflater inflater = LayoutInflater.from(this); 47 for(int i = 0 ; i< mPics.size() ; i++){ 48 View view = inflater.inflate(R.layout.item_picture_view,null); 49 mViews.add(view); 50 } 51 52 MyAdapter adapter = new MyAdapter(mViews,mPics,this); 53 mViewPager.setAdapter(adapter); 54 mViewPager.setCurrentItem(index); 55 index += 1; //設置當前圖片指示器 56 tv_hint01.setText(""+index); 57 } 58 59 private void setEvent() { 60 mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 61 @Override 62 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 63 64 } 65 @Override 66 public void onPageSelected(int position) { 67 index = position+1; //設置當前圖片指示器 68 tv_hint01.setText(""+index); 69 } 70 @Override 71 public void onPageScrollStateChanged(int state) { 72 73 } 74 }); 75 } 76 77 @Override 78 public boolean onKeyDown(int keyCode, KeyEvent event) { 79 if(keyCode == KeyEvent.KEYCODE_BACK){ 80 MyApplication.getInstance().deleteActivity("PhotoScan",PhotoScan.this); 81 } 82 return super.onKeyDown(keyCode, event); 83 } 84 85 private class MyAdapter extends PagerAdapter{ 86 List<View> mViews; 87 List<String> mPics; 88 Context context; 89 public MyAdapter(List<View> mViews,List<String> mPics,Context context){ 90 this.mViews = mViews; 91 this.mPics = mPics; 92 this.context = context; 93 } 94 //viewpager中的組件數量 95 @Override 96 public int getCount() { 97 return mViews.size(); 98 } 99 100 //滑動切換的時候銷毀當前的組件 101 @Override 102 public void destroyItem(ViewGroup container, int position, Object object) { 103 ((ViewPager)container).removeView(mViews.get(position)); 104 } 105 106 //每次滑動的時候,生成組件 107 @Override 108 public Object instantiateItem(ViewGroup container, int position) { 109 View view = mViews.get(position); 110 mImageView = ((ImageView) view.findViewById(R.id.iv)); 111 String picurl = mPics.get(position); 112 setPic(picurl,view); 113 ((ViewPager)container).removeView(mViews.get(position)); 114 ((ViewPager)container).addView(mViews.get(position)); 115 return mViews.get(position); 116 } 117 118 @Override 119 public boolean isViewFromObject(View view, Object object) { 120 return view == object; 121 } 122 123 @Override 124 public int getItemPosition(Object object) { 125 return super.getItemPosition(object); 126 } 127 } 128 129 /** 130 * 加載網絡圖片 131 */ 132 private void setPic(String picurl, final View parentView){ 133 if(!picurl.contains("http://") && imageType == 0) { 134 picurl = MyConfig.picFirst+picurl; 135 } 136 if(imageType == 1){ //"/mnt/sdcard/mImageView.png" 137 picurl = ImageDownloader.Scheme.FILE.wrap(picurl); 138 } 139 Log.i("main",picurl); 140 //加載自定義配置的一個圖片的,網絡加載監聽,等待加載圖片完成再初始化縮小放大 141 ImageLoader.getInstance().displayImage(picurl, mImageView, MyApplication.OptionsNoCache, new SimpleImageLoadingListener() { 142 @Override 143 public void onLoadingStarted(String imageUri, View view) { 144 super.onLoadingStarted(imageUri, view); 145 Utility.setLoadingProgressbar(null,parentView,true); 146 } 147 148 @Override 149 public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { 150 super.onLoadingComplete(imageUri, view, loadedImage); 151 Utility.setLoadingProgressbar(null,parentView,false); 152 mAttacher = new PhotoViewAttacher(mImageView); 153 mAttacher.update(); 154 } 155 }, new ImageLoadingProgressListener() { 156 @Override 157 public void onProgressUpdate(String s, View view, int i, int i1) { 158 Log.i("main","i="+i+",il="+i1); 159 } 160 }); 161 162 } 163 }
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:orientation="vertical" 7 > 8 <include 9 layout="@layout/ll_progessbar1" 10 /> 11 <ImageView 12 android:id="@+id/iv" 13 android:layout_width="match_parent" 14 android:layout_height="match_parent" 15 android:scaleType="centerInside" 16 > 17 </ImageView> 18 </LinearLayout>
mViews<View>存放在(包含)ImageView的引用,隨着imageView設置Bitmap的增加,大概30張大圖之后就基本OOM了,這時要做優化修改:
1、修改mViews的大小,默認只有4個
1 for(int i = 0 ; i< 4 ; i++){ 2 View view = inflater.inflate(R.layout.item_picture_view,null); 3 mViews.add(view); 4 }
2、修改容器里面關於mViews的使用
private class MyAdapter extends PagerAdapter{
List<View> mViews;
List<String> mPics;
Context context;
public MyAdapter(List<View> mViews,List<String> mPics,Context context){
this.mViews = mViews;
this.mPics = mPics;
this.context = context;
}
//viewpager中的組件數量
@Override
public int getCount() {
return mPics.size();
}
//滑動切換的時候銷毀當前的組件
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
int i = position%4;
Log.i("main","正在銷毀第幾頁:"+position+",正在銷毀對應mViews的第幾個數據源:"+i);
((ViewPager)container).removeView(mViews.get(i));
}
//每次滑動的時候,生成組件
@Override
public Object instantiateItem(ViewGroup container, int position) {
int i = position%4;
View view = mViews.get(i);
mImageView = ((ImageView) view.findViewById(R.id.iv));
String picurl = mPics.get(position);
setPic(picurl,view);
Log.i("main","正在生成第幾頁:"+position+",正在調用mViews的第幾個數據源:"+i);
((ViewPager)container).addView(mViews.get(i));
return mViews.get(i);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public int getItemPosition(Object object) {
return super.getItemPosition(object);
}
}
/**
* 加載網絡圖片
*/
private void setPic(String picurl, final View parentView){
if(!picurl.contains("http://") && imageType == 0) {
picurl = MyConfig.picFirst+picurl;
}
if(imageType == 1){ //"/mnt/sdcard/mImageView.png"
picurl = ImageDownloader.Scheme.FILE.wrap(picurl);
}
Log.i("main",picurl);
//加載自定義配置的一個圖片的,網絡加載監聽,等待加載圖片完成再初始化縮小放大
ImageLoader.getInstance().displayImage(picurl, mImageView, MyApplication.OptionsWithCache, new SimpleImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
super.onLoadingStarted(imageUri, view);
Utility.setLoadingProgressbar(null,parentView,true);
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
Utility.setLoadingProgressbar(null,parentView,false);
mAttacher = new PhotoViewAttacher(mImageView);
mAttacher.update();
}
}, new ImageLoadingProgressListener() {
@Override
public void onProgressUpdate(String s, View view, int i, int i1) {
Log.i("main","i="+i+",il="+i1);
}
});
}
也就是說,整個方案中最多只保存3個ImageView,建立4個數據源的mViews,那時因為ViewPager在滑動的時候:
打開第一頁時:
第2頁、第3頁:
第4頁、第5頁:
第5頁-》第4頁:
這里可以看到,從第2頁滑動向第3頁時,是先銷毀第1頁,再構造第3頁,也就是先destoryItem再InstantiateItem,而銷毀和構造ViewPager視圖的都是用到同一個mView.get(i)(如從第2-》3頁,銷毀和構造都是0;從第4-》5頁,銷毀和構造都是2),這里是無問題的;
但是,如果從第5頁滑到回來第4頁就出問題了,這里是先構造第4頁的前前一頁,也就是第2頁,銷毀的時候,正在被當前視圖使用,這里就會出錯了。所有改用包含4個子項的mViews
最后上一個修改之后的log,頁數變化如:1-2-3-4-5-6-5-4