onClickListener仅在几次单击后才起作用

时间:2017-07-08 13:03:01

标签: java android listview android-adapter android-viewholder

我知道这不是一个非常好的问题描述,但我偶然发现了ListAdapter的不稳定行为。

关键是,我的应用程序中的onItemClickListener只响应了经常点击的时间。调试器也只在这种情况下响应。不过,点击工作不时很好。好像有东西在内部阻止onItemClickListener被bein调用。有时甚至默认的android点击动画也不会在第一次点击时显示。虽然,经过2-5次快速点击后,一个接一个地总是按预期工作。

刚接触Android开发,我不知道从哪里开始寻找问题。问题不是特定于设备(已测试)。

以防万一,我项目中的一些代码(虽然我甚至不确定要提供什么):

来自OffersListAdapter的一些代码:

class ViewHolder {
    private TextView whoandWhom;
    private TextView date;
    private TextView distance;

    private TextView status;
    private TextView place;

    private boolean isMeeting = false;
    private Meeting.Status meetingStatus;

    private void color(int color) {
        for (Field v: this.getClass().getDeclaredFields()) {
            try {
                if (v.getType() == TextView.class) {
                    TextView view = (TextView) v.get(this);
                    view.setTextColor(res.getColor(color));
                }
            } catch (IllegalAccessException e) {
                Log.e("ERROR", "This field does not exist");
            }
        }
    }
}
private View prepareHolder(boolean isMeeting, View convertView, Meeting.Status mStatus, Offer offer) {
    ViewHolder holder = new ViewHolder();

    LayoutInflater li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (isMeeting) {
        convertView = li.inflate(R.layout.meetings_item, null);
    } else {
        convertView = li.inflate(R.layout.offers_item, null);
    }
    holder.whoandWhom = (TextView)convertView.findViewById(R.id.datetime);
    holder.date = (TextView)convertView.findViewById(R.id.dateTime);
    holder.distance = (TextView)convertView.findViewById(R.id.distance);

    if (isMeeting) {
        holder.isMeeting = true;
        holder.status = (TextView)convertView.findViewById(status);
        holder.place = (TextView)convertView.findViewById(place);
        holder.meetingStatus = mStatus;
    }

    convertView.setTag(holder);

    holder.whoandWhom.setText(offer.getOwnership());
    holder.date.setText(offer.getDateRepresentation());
    String distance = new DecimalFormat("#####.##").format(offer.getDistance()) + " км";
    holder.distance.setText(distance);

    if (isMeeting) {
        Meeting meeting = (Meeting) offer;
        holder.place.setText(meeting.getPlace_name());
        switch (meeting.getStatus()) {
            case pending:
                holder.status.setText("Очікує підтвердження");
                break;
            case upcoming:
                holder.status.setText("Незабаром");
                holder.color(R.color.colorAccent);
                break;
            case completed:
                holder.status.setText("Завершено");
                holder.color(R.color.colorPrimary);
                break;
        }
    }

    return convertView;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    ViewHolder holder;
    Offer offer = this.getItem(position);
    Boolean isMeeting = offer.getClass() == Meeting.class;

    Meeting.Status status = null;
    if (isMeeting)
        status = ((Meeting) offer).getStatus();

    if (convertView == null) {
        convertView = prepareHolder(isMeeting, convertView, status, offer);
    } else {
        holder = (ViewHolder) convertView.getTag();
        if (isMeeting != holder.isMeeting)
            convertView = prepareHolder(isMeeting, convertView, status, offer);
        else if (isMeeting) {
            if (status != holder.meetingStatus)
                convertView = prepareHolder(true, convertView, status, offer);
        }
    }

    return convertView;
}

MainActivity的一些方法:

private void configureOffersOutput() {
    offersOutput = (ListView) findViewById(R.id.offersOutput);
    offersList = new ArrayList<Offer>();

    LayoutInflater li = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    loadingView = li.inflate(R.layout.list_footer_view, null);

    adapter = new OffersListAdapter(getApplicationContext(), offersList, getResources());

    configureOnItemClick();
    offersOutput.setAdapter(adapter);

    offersOutput.setNestedScrollingEnabled(true);
    offersOutput.setOnScrollListener(new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {}
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            if (view.getLastVisiblePosition() >= totalItemCount - 1 && !isLoading) {
                moreOffers();
            }
        }
    });
}


private void configureOnItemClick() {

    final Activity a = this;

    offersOutput.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            final Offer item = offersList.get(position);
            if (item.getClass() == Offer.class) {

                openActivity(a, SuggestActivity.class, new HashMap<String, String>() {{
                    put("id", item.getId());
                    put("location", item.getLocation());
                    put("datetime", item.getDateRepresentation());
                    put("ownership", item.getOwnership());

                    put("currentCoordinates", coordinates);
                    put("token", user.getToken());
                    put("uid", user.getId());
                }});

            } else if (item.getClass() == Meeting.class) {

                final Meeting meeting = (Meeting) item;
                Class<?> name;

                switch (meeting.getStatus()) {
                    case pending:
                        name = ApproveActivity.class;
                        break;
                    case upcoming:
                        name = UpcomingActivity.class;
                        break;
                    case completed:
                        name = RateActivity.class;
                        break;
                    default:
                        name = MeetingActivity.class;
                        Log.e("ERROR", "Wrong status: " + meeting.getStatus().toString());
                }

                final String distance = new DecimalFormat("#####.##").format(meeting.getDistance()) + " км";

                openActivity(a, name, new HashMap<String, String>(){{
                    put("id", meeting.getId());
                    put("datetime", meeting.getDateRepresentation());
                    put("ownership", meeting.getOwnership());

                    put("tel", meeting.getTel());
                    put("distance", distance);
                    put("place", meeting.getPlace_name());
                    put("place_coordinates", meeting.getPlace_coordinates());

                    put("currentCoordinates", coordinates);
                    put("token", user.getToken());
                    put("uid", user.getId());
                }});

            }
        }
    });

    initRefresh();

    isSetItemOnClick = true;
}

1 个答案:

答案 0 :(得分:0)

好的,所以我想出了一个答案,万一有人遇到同样的问题。

除此之外,我还有一个响应滚动事件的方法。它将按下滚动加载数据:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Test File | Vanilla JS</title>
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
	</head>
	<body>
	
		<div class="wrapperSlider">
			<div id="slider">
				<div class="sliderItems">
					<div>Item 1</div>
				</div>
				<div class="sliderItems">
					<div>Item 2</div>
				</div>
				<div class="sliderItems">
					<div>Item 3</div>
				</div>
				<div class="sliderItems">
					<div>Item 4</div>
				</div>
				<div class="sliderItems">
					<div>Item 5</div>
				</div>
			</div>
		</div>
		
		<div class="wrapperPaging">
			<div id="pagingSlider">
				<span class="pagingItems">1</span>
				<span class="pagingItems">2</span>
				<span class="pagingItems">3</span>
				<span class="pagingItems">4</span>
				<span class="pagingItems">5</span>
			</div>
		</div>
		
	</body>
</html>

window.addEventListener('load', function(){ jQuery('#cookie-message-close').click(function(){ jQuery('#cookie-message').hide(); }); if (!Cookies.get("cookie-message-bar")) { jQuery('#cookie-message').show(); Cookies.set('cookie-message-bar', true, { expires: 60 }); } }); 会向后端发送请求并加载行。

问题是:

  1. DB很快就用完了行,因此会收到空的结果
  2. 应用程序如此快速地发送了请求,并经常尝试刷新行,以至于他们大部分时间都无法响应触摸。
  3. 解决方案(虽然丑陋): 添加到从DB接收数据的方法:

    ffersOutput.setNestedScrollingEnabled(true);
        offersOutput.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {}
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if (view.getLastVisiblePosition() >= totalItemCount - 1 && !isLoading) {
                    moreOffers();
                }
            }
        });
    

    这会阻止应用经常发出请求,因此可以做出响应。

相关问题