控件一:Gallery 之滑动不流畅的解决办法 异步加载

Gallery滑动的时候之所以会卡,是因为当它滑动到中间的时候,默认会为选中状态,那么这个时候就要去加载图片,如果当图片比较大的时候,就会导致卡一下。

一、通过异步加载图片的方式

其余的地方不变,只是在Adapter中使用异步加载的方式。

public class GalleryAdapter extends BaseAdapter { private ImageView[] imageView;// 加载图片的imageView数组 private Context context; private Integer[] imagesId;// 要显示的图片 public GalleryAdapter(Context context) { this.context = context; imagesId = new Integer[] { R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d }; imageView = new ImageView[imagesId.length]; } public int getCount() { return imagesId.length; } public Object getItem(int position) { Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), imagesId[position]); return bitmap; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { if (imageView[position] == null) imageView[position] = new ImageView(context); new MyTask().execute(position);//开启异步任务加载图片 imageView[position].setLayoutParams(new MyGallery.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); return imageView[position]; } private class MyTask extends AsyncTask<Integer, Void, Void> { private Bitmap bitmap; private int position; @Override protected Void doInBackground(Integer... params) { //在这里加载图片 position = params[0]; BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; bitmap = BitmapFactory.decodeResource(context.getResources(), imagesId[params[0]], options); return null; } @Override protected void onPostExecute(Void result) { //因为该方法是由UI线程调用,所以在这里设置ImageView的图片 super.onPostExecute(result); imageView[position].setImageBitmap(bitmap); } } }

二、上面的方法,虽然是异步加载,可是,是先开启加载,在显示图片,所以,被选中的ImageView会黑一下。而且不知道为什么,理论上异步加载是不会卡的,可是,用这种方法加载更大一点的图片,还是会卡一下,而且卡的很奇怪,总是在移到某一张图片的时候,在往后面移动, 会先弹出下下一张图片的一小部分,然后,才显示下一张图片。这中间会小卡一下,不明白原因啊!!所以想了下,采用了下面的方法改进。

每次缓冲3张,让ImageView先显示,再去异步加载图片

先看Adapter的代码:


public class GalleryAdapter extends BaseAdapter { private Context context; private Integer[] imagesId;// 要显示的图片 private Bitmap[] nearBitmaps;// 自己所缓存的当前图片附近的图片,当前图片是1,上一张是0,下一张是2 private int showingIndex;// 正在显示的图片是第几张图片 public GalleryAdapter(Context context, Integer[] imagesId) { this.context = context; this.imagesId = imagesId; nearBitmaps = new Bitmap[3]; // 最开始的时候,先初始化最开始的3张图片 BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; nearBitmaps[1] = BitmapFactory.decodeResource(context.getResources(), imagesId[0], options); nearBitmaps[2] = BitmapFactory.decodeResource(context.getResources(), imagesId[1], options); } public int getCount() { return imagesId.length; } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = new ImageView(context); convertView.setLayoutParams(new MyGallery.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); } if (position == showingIndex) ((ImageView)convertView).setImageBitmap(nearBitmaps[1]); if (position == showingIndex - 1) {//说明是向前滑动 ((ImageView)convertView).setImageBitmap(nearBitmaps[0]); } if (position == showingIndex + 1) {//说明是向后滑动 ((ImageView)convertView).setImageBitmap(nearBitmaps[2]); } return convertView; } public Bitmap[] getNearBitmaps() { return nearBitmaps; } public int getShowingIndex() { return showingIndex; } public void setShowingIndex(int showingIndex) { this.showingIndex = showingIndex; } 



Activity中的代码:

public class ImageScanActivity extends Activity {
	private MyGallery gallery;
	private GalleryAdapter adapter;
	//图片数组
	private Integer[] imagesId = new Integer[] { R.drawable.a, R.drawable.b, R.drawable.c,
			R.drawable.d, R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.a,
			R.drawable.b, R.drawable.c, R.drawable.d };

	private int motionStatus=0;//记录到底是向前滑动,还是向后,-1向前,1向后
	@Override
	public void onCreate(Bundle savedInstanceState) {
		
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		gallery = (MyGallery) findViewById(R.id.gallery);
		adapter = new GalleryAdapter(this,imagesId);
		gallery.setAdapter(adapter);
		gallery.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
			public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
				if(position==adapter.getShowingIndex()-1){//向前
					new MyTask().execute();
					motionStatus=-1;
				}
				if(position==adapter.getShowingIndex()+1){//向后
					motionStatus=1;
					new MyTask().execute();
				}
			}
			public void onNothingSelected(AdapterView<?> parent) {

			}
		});
	}
	private class MyTask extends AsyncTask<Void, Void, Void> {
		@Override
		protected Void doInBackground(Void... params) {
			int showing = adapter.getShowingIndex();// 记录当前正在显示图片的id
			Bitmap[] bitmaps = adapter.getNearBitmaps();//获得Adapter中的缓存图片数组
			BitmapFactory.Options options = new BitmapFactory.Options();
			options.inSampleSize = 2;
			if(motionStatus==-1){//向前滑动,bitmaps[0]加载新的图片
				bitmaps[2]=bitmaps[1];
				bitmaps[1]=bitmaps[0];
				if(showing>=2)
				bitmaps[0]=BitmapFactory.decodeResource(getResources(), imagesId[showing - 2],
						options);
			}
			if(motionStatus==1){//向后滑动,bitmaps[2]加载新的图片
				bitmaps[0]=bitmaps[1];
				bitmaps[1]=bitmaps[2];
				if(showing<=imagesId.length-3)
				bitmaps[2]=BitmapFactory.decodeResource(getResources(), imagesId[showing + 2],
						options);
			}
			adapter.setShowingIndex(showing+motionStatus);
			return null;
		}
	}
}



 

反正,就是先缓存几张图片,然后,根据移动,在加载图片,因为如果一次加载太多了,容易内存泄漏。

感觉这样做,真是吃力不讨好,可是又实在想不出什么好的办法。而且当快速滑动的时候,grallery还会黑,刷新不出图片了,虽然可以解决,可是太麻烦了,而且又会搞的有点卡。

到底怎么一劳永逸的解决这个卡的问题,求指教啊!!!

 
 
 

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值