源于一个bug.这个bug的是这样.下面是一个girdview当用户反复点击某一个自定义item的时候,比如说是1 ,会导致item 3响应.查了一下原因是由于
onclick实现的架构错误引起的,监听器源代码如下
this.setOnTouchListener( new OnTouchListener() {
@Override
public boolean onTouch(
View v ,
MotionEvent event )
{
// TODO Auto-generated method stub
if( event.getAction() == MotionEvent.ACTION_MOVE || event.getAction() == MotionEvent.ACTION_DOWN )
{
if( appinfo.getCurrentstate() == ApplicationInfo.APP_PAUSE || appinfo.getCurrentstate() == ApplicationInfo.APP_DOWNLOADING
|| appinfo.getCurrentstate() == ApplicationInfo.APP_DOWNLOAD_COMPLATE)
{
virtualOrRealAppBackgroud( false );
}
else
{
virtualOrRealAppBackgroud( true );
}
}
else
{
if( appinfo.getCurrentstate() == ApplicationInfo.APP_PAUSE || appinfo.getCurrentstate() == ApplicationInfo.APP_DOWNLOADING
|| appinfo.getCurrentstate() == ApplicationInfo.APP_DOWNLOAD_COMPLATE)
{
virtualOrRealAppBackgroud( true );
}
else
{
virtualOrRealAppBackgroud( false );
}
}
return false;
}
} );
this.setOnClickListener( new OnClickListener() {
@Override
public void onClick(
View v )
{
// TODO Auto-generated method stub
//this is patch,because when downloading to pause will waste long time(almost 500ms).
if( appinfo.getCurrentstate() == ApplicationInfo.APP_DOWNLOADING )
{
virtualOrRealAppBackgroud( true );
badgeViewHolder.badge.setBackgroundDrawable( getResources().getDrawable( R.drawable.operatestart ) );
badgeViewHolder.badge.setBadgePosition( BadgeView.POSITION_CENTER );
badgeViewHolder.badge.show();
}
ChoiceApplication.getInstance().mDynamicEntrce.processIcon( AppView.this.appinfo );
baseAdapter.notifyDataSetChanged();
Log.v( "MyOpt" , "setOnClickListener" );
}
} );
}
刷新adapter的getview函数
@Override
public View getView(
int position ,
View convertView ,
ViewGroup parent )
{
if( title.getVisibility() == View.INVISIBLE )
{
title.setVisibility( View.VISIBLE );
}
ApplicationInfo appinfo = mAllAppsList.get( position );
if( convertView == null )
{
convertView = new AppView( getContext() , appinfo , this );
}
else
{
( (AppView)convertView ).updateaAppView( appinfo );
}
return convertView;
}
}
错误的原因就在data(appinfo)成为了AppView的一个成员,而getview中利用了view缓存更新成员appinfo,这样导致当用户快速点击adapter调用getview速度没有更上.
比如说点击的item 1的view,但是有可能它是利用了item 2 view的缓存,恰好刷新的速度没有更上,item 2 view关联的 data还是 item 2的data,就导致了如上Bug.
如何修正?
girdview中自定义view的监听提取出来放在girdview的onitemlistener中去实现,这样就不会导致刷新频率跟不上监听事件.
gridView.setOnItemClickListener( new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(
AdapterView<?> parent ,
View view ,
int position ,
long id )
{
// TODO Auto-generated method stub
//this is patch,because when downloading to pause will waste long time(almost 500ms).
if( mAllAppsList.get(position).getCurrentstate() == ApplicationInfo.APP_DOWNLOADING )
{
mAllAppsList.get(position).setCurrentstate(ApplicationInfo.APP_PAUSE);
imageAdapter.notifyDataSetChanged();
mAllAppsList.get(position).setCurrentstate(ApplicationInfo.APP_DOWNLOADING);
}
ChoiceApplication.getInstance().mDynamicEntrce.processIcon( mAllAppsList.get(position) );
}
} );
这里又有一个新的问题
每一个自定义view需要有按下的效果是通过setOnTouchListener()实现的,但是如果在girdview去设置了setOnItemClickListener,自定义view是触发到setOnTouchListener事件的, 这个原因我也不知道为什么?
那么只好把setOnTouchListener放置在girdview的setOnTouchListener,代码如下:
private boolean itempressflag = false; //in order to each touch only touch one item
private int itempressposition = -1; //record each touch position
private void setListeners()
{
if( gridView != null )
{
gridView.setSelector( new ColorDrawable( Color.TRANSPARENT ) );
gridView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
float currentXPosition = event.getX();
float currentYPosition = event.getY();
int position = gridView.pointToPosition((int) currentXPosition, (int) currentYPosition);
//position no equal to -1 prevent don't touch effective area
//itempressflag must is false because should to prevent touch more than one item.
if(position != -1 && !itempressflag ){
if( event.getAction() == MotionEvent.ACTION_MOVE || event.getAction() == MotionEvent.ACTION_DOWN )
{
itempressflag = true;
itempressposition = position;
if( mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_PAUSE || mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_DOWNLOADING
|| mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_DOWNLOAD_COMPLATE)
{
((AppView)gridView.getChildAt(itempressposition)).virtualOrRealAppBackgroud( false );
}
else
{
((AppView)gridView.getChildAt(itempressposition)).virtualOrRealAppBackgroud( true );
}
}
}else{
if(itempressflag){
if(position != itempressposition){
if( mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_PAUSE || mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_DOWNLOADING
|| mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_DOWNLOAD_COMPLATE)
{
((AppView)gridView.getChildAt(itempressposition)).virtualOrRealAppBackgroud( true );
}
else
{
((AppView)gridView.getChildAt(itempressposition)).virtualOrRealAppBackgroud( false );
}
}
if(event.getAction() == MotionEvent.ACTION_UP){
if( mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_PAUSE || mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_DOWNLOADING
|| mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_DOWNLOAD_COMPLATE)
{
((AppView)gridView.getChildAt(itempressposition)).virtualOrRealAppBackgroud( true );
}
else
{
((AppView)gridView.getChildAt(itempressposition)).virtualOrRealAppBackgroud( false );
}
itempressflag = false;
itempressposition = -1;
}
}
}
return false;
}
});
总结:
1,如果girdview中的每一个sub view与数据相关联,不要在sub view中写监听器
2,girdview item同时实现onclick和ontouch同时实现的方式