Адаптер, таймеры и многопоточность. Android.

Всем привет! Столкнулся со следующей проблемой:
Общий таск: android приложение-мессенджер для общения с саппортом интернет-провайдера.
Трабла: Необходимо реализовать в списке чатов таймеры отсчета ожидания ответа оператора и клиента.
Что происходит: Проблема с мултипоточностью - один поток перекрывает рендеринг всех остальных.
Нагдяно можно посмотреть тут: https://drive.google.com/file/d/0B_SjoeZavdZwdXlUQlU3QTVKeG8/view?usp=sharing
Где посмотреть код: https://gist.github.com/scrobot/3e8e0b8874707f671bb792eed63f8fea
Для ленивых - выкладываю гифку и код здесь)
https://imgflip.com/gif/13meq5
public class SessionAdapter extends BaseAdapter {
private static final String TAG = SessionAdapter.class.toString();
List<SessionInterface> sessions = new ArrayList<>();
Context context;
private Message mLastMessage;
private List<ViewHolder> lstHolders;
private Handler mHandler = new Handler();
private Runnable updateRemainingTimeRunnable = new Runnable() {
@Override
public void run() {
synchronized (lstHolders) {
long currentTime = System.currentTimeMillis();
for (ViewHolder holder : lstHolders) {
holder.updateTimeRemaining(currentTime, 0);
}
}
}
};
public SessionAdapter(List<SessionInterface> sessions, Context context) {
this.sessions = sessions;
this.context = context;
lstHolders = new ArrayList<>();
startUpdateTimer();
}
public void updateSessions(List<SessionInterface> sessionInterface) {
this.sessions = sessionInterface;
}
@Override
public int getCount() {
return sessions.size();
}
@Override
public SessionInterface getItem(int position) {
return sessions.get(position);
}
@Override
public long getItemId(int position) {
SessionInterface session = sessions.get(position);
return session.getId();
}
public long getPositionById(long id) {
for (int i = 1; i < sessions.size(); i++) {
long sessionId = getItemId(i);
Log.d(TAG, "getPositionById-i: " + i);
Log.d(TAG, "getPositionById-id: " + id);
Log.d(TAG, "getPositionById-sessionId: " + sessionId);
boolean eq = id == sessionId;
Log.d(TAG, "getPositionById-sessionId==id: " + eq);
if(eq) {
return i;
}
}
return 0;
}
private void startUpdateTimer() {
Timer tmr = new Timer();
tmr.schedule(new TimerTask() {
@Override
public void run() {
mHandler.post(updateRemainingTimeRunnable);
}
}, 1000, 1000);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final SessionInterface session = sessions.get(position);
ViewHolder holder;
mLastMessage = session.getMessages().get(session.getMessages().size() - 1);
if(convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.adapter_sessions, null);
holder.label = (TextView) convertView.findViewById(R.id.label);
holder.sessionTitle = (TextView) convertView.findViewById(R.id.ticket_title);
holder.date = (TextView) convertView.findViewById(R.id.date);
holder.message = (TextView) convertView.findViewById(R.id.comment);
holder.status = (TextView) convertView.findViewById(R.id.status);
holder.chatStatusImage = (ImageView) convertView.findViewById(R.id.ticket_status);
holder.timeRemaining = (TextView) convertView.findViewById(R.id.time_remaining);
convertView.setTag(holder);
synchronized (lstHolders) {
lstHolders.add(holder);
}
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.label.setText("Чат #" + session.getId());
holder.sessionTitle.setText(Helpers.stringLimit(session.getQueue().getName(), 30));
try {
Date jud = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss", new Locale("ru")).parse(mLastMessage.getDate());
String targetFormat = new SimpleDateFormat("d MMMM, HH:mm", new Locale("ru")).format(jud);
long milliseconds = jud.getTime();
holder.date.setText(targetFormat);
if(session.getClosedTimeAgo() == null) {
// Log.d(TAG, "Sid: " + session.getId() + " ;\nnow: " + System.currentTimeMillis() + ";\n last date: " + mLastMessage.getDate() + "; \nmill: " + milliseconds );
holder.updateTimeRemaining(System.currentTimeMillis(), milliseconds);
holder.timeRemaining.setVisibility(View.VISIBLE);
} else {
holder.timeRemaining.setVisibility(View.GONE);
}
} catch (ParseException e) {
e.printStackTrace();
}
holder.message.setText(Helpers.stringLimit(Helpers.stripLineBreaks(mLastMessage.getText(), " "), 50));
if(session.getIs_closed() == 1) {
holder.setClosed(convertView);
} else {
if(mLastMessage.getSender_type().equals(Constants.CLIENT_TYPE)) {
holder.setClientWaiting(convertView);
} else {
holder.setOperatorWaiting(convertView);
}
}
return convertView;
}
private class ViewHolder {
TextView label;
TextView sessionTitle;
TextView date;
TextView message;
TextView status;
ImageView chatStatusImage;
TextView timeRemaining;
public void updateTimeRemaining(long currentTime, long timeAgo) {
Log.d(TAG, "updateTimeRemaining:\n currentTime - " + currentTime + ";\n timeAgo - " + timeAgo + ";\n timeDiff(currentTime - timeAgo) = " + (currentTime - timeAgo));
Log.d(TAG, "updateTimeRemaining:\n currentTime - " + currentTime + ";\n timeAgo - " + timeAgo + ";\n timeDiff(timeAgo - currentTime) = " + (timeAgo - currentTime));
long timeDiff = currentTime - timeAgo;
if (timeDiff > 0) {
int seconds = (int) (timeDiff / 1000) % 60;
int minutes = (int) ((timeDiff / (1000 * 60)) % 60);
int hours = (int) ((timeDiff / (1000 * 60 * 60)) % 24);
int hourMinutes = hours*60 + minutes;
timeRemaining.setText(hourMinutes + ":" + (seconds < 10 ? "0" + seconds : seconds));
} else {
timeRemaining.setText("Expired!!");
}
}
public void setClosed(View convertView) {
this.status.setText("Закрыто");
this.status.setTextColor(convertView.getResources().getColor(R.color.closedText));
this.chatStatusImage.setImageDrawable(convertView.getResources().getDrawable(R.drawable.chat_status_closed));
}
public void setOperatorWaiting(View convertView) {
this.status.setText("Оператор ожидает ваш ответ");
this.status.setTextColor(convertView.getResources().getColor(R.color.clientColor));
this.timeRemaining.setTextColor(convertView.getResources().getColor(R.color.clientColor));
this.chatStatusImage.setImageDrawable(convertView.getResources().getDrawable(R.drawable.chat_status_client));
}
public void setClientWaiting(View convertView) {
this.status.setText("Ожидается ответ оператора");
this.status.setTextColor(convertView.getResources().getColor(R.color.operatorColor));
this.timeRemaining.setTextColor(convertView.getResources().getColor(R.color.operatorColor));
this.chatStatusImage.setImageDrawable(convertView.getResources().getDrawable(R.drawable.chat_status_operator));
}
}
}
Помогите решить эту проблемку, пожалуйста)) Заранее спасибо за ваши ответы!)
05 мая 2016 в 08:56
Ближайшие курсы

Как начать свой путь в разработке?
Онлайн-курс
1
марта
Стартуй в веб-разработке
Онлайн-курс
1
марта

Java. Уровень 3
Профессиональная разработка программного обеспечения
1
марта
Новые статьи

Как защитить Windows: системный подход
74800

«После Scratch поняла, что не хочу бросать программирование»
125610

Что такое MVP и зачем его делать
85700