我知道这不是一个非常好的问题描述,但我偶然发现了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;
}
答案 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 });
}
});
会向后端发送请求并加载行。
问题是:
解决方案(虽然丑陋): 添加到从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();
}
}
});
这会阻止应用经常发出请求,因此可以做出响应。