2017-07-08 1 views
0

Je sais que ce n'est pas une très bonne description du problème, mais je suis tombé dans le comportement instable de mon ListAdapter.onClickListener ne fonctionne qu'après plusieurs clics

Le point est, onItemClickListener dans mon application ne répond que si temps sereral furieusement cliqué. Le débogueur répond également seulement dans une telle situation. Néanmoins, de temps en temps, les clics fonctionnent très bien. Il semble que quelque chose empêche intérieurement le onItemClickListener de bein appelé. Parfois même l'animation de clic android par défaut n'est pas affichée au premier clic. Bien que, après 2-5 clics rapides l'un après l'autre fonctionne toujours comme prévu. Étant nouveau dans le développement Android, je ne sais pas par où commencer à chercher le problème. Le problème n'est pas spécifique à l'appareil (testé).

Juste au cas où, un code de mon projet (bien que je ne suis même pas sûr de ce à fournir):

Une partie du code de 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; 
} 

Certaines méthodes de 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

où est votre écouteur onclick –

+0

S'il vous plaît vous signaler onClickListener, Aussi cela m'était arrivé avant et c'était parce que je implémente deux écouteurs de l'activité et de l'adaptateur pour la même vue. –

+0

offersOutput.setonItemClickListerner? – Jamil

Répondre

0

Ok, donc je compris une réponse juste au cas où quelqu'un a le même problème. En plus de tout cela, j'avais une méthode répondant aux événements de défilement. Il charge les données défilement vers le bas comme ceci:

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(); 
      } 
     } 
    }); 

moreOffers serait que d'envoyer une demande de backend et charger les lignes.

Le problème était:

  1. DB a manqué de lignes très rapidement, de sorte qu'il recevrait des résultats vides
  2. App a envoyé des demandes si rapidement et si souvent essayé des lignes rafraîchissants qu'ils la plupart des wouldn temps » t être capable de répondre aux touches.

Solution (bien que laid): Ajouter à la méthode qui reçoit des données de DB quelque chose comme ceci:

new Timer().schedule(new TimerTask() { 
    @Override 
    public void run() { 
     isLoading = false; 
    } 
}, 100); 

qui empêche l'application de faire des demandes si souvent, il peut donc y répondre.