package io.github.memfis19.cadar.internal.ui.month.adapter; import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.Process; import android.support.v7.widget.RecyclerView; import java.util.ArrayList; import java.util.Calendar; import java.util.List; /** * Created by memfis on 7/25/16. * Helper class to fill the month adapter asynchronously */ public class MonthHandlerThread extends HandlerThread { private static final String TAG = "MonthHandlerThread"; private static final int REQUEST_MONTH_PREPARATION = 852; private static final int NUM_OF_DAYS_IN_WEEK = 7; private class MonthInfoDto { private Calendar calendar; private Integer shiftValue; private RecyclerView recyclerView; MonthInfoDto(Calendar calendar, Integer shiftValue, RecyclerView recyclerView) { this.calendar = calendar; this.shiftValue = shiftValue; this.recyclerView = recyclerView; } } interface AdapterPrepareListener { void onReadyAdapter(Calendar month, List<Calendar> monthDays, RecyclerView recyclerView); } private boolean hasQuit = false; private Handler requestHandler; private Handler responseHandler; private AdapterPrepareListener adapterPrepareListener; public MonthHandlerThread() { super(TAG, Process.THREAD_PRIORITY_BACKGROUND); } void setAdapterPrepareListener(AdapterPrepareListener adapterPrepareListener) { this.adapterPrepareListener = adapterPrepareListener; } @Override protected void onLooperPrepared() { responseHandler = new Handler(Looper.getMainLooper()); requestHandler = new Handler(Looper.myLooper()) { @Override public void handleMessage(Message msg) { if (msg.what == REQUEST_MONTH_PREPARATION) { handlePreparation((MonthInfoDto) msg.obj); } } }; } @Override public boolean quit() { hasQuit = true; return super.quit(); } @Override public boolean quitSafely() { hasQuit = true; return (Build.VERSION.SDK_INT > 17) ? super.quitSafely() : super.quit(); } void queuePreparation(Calendar calendar, Integer shiftValue, RecyclerView recyclerView) { if (hasQuit || requestHandler == null) return; requestHandler.obtainMessage(REQUEST_MONTH_PREPARATION, new MonthInfoDto(calendar, shiftValue, recyclerView)).sendToTarget(); } private void handlePreparation(final MonthInfoDto monthInfoDto) { final Calendar month = (Calendar) monthInfoDto.calendar.clone(); month.add(Calendar.MONTH, monthInfoDto.shiftValue); month.set(Calendar.DAY_OF_MONTH, 1); final List<Calendar> monthDays = prepare(month); if (!hasQuit && adapterPrepareListener != null) responseHandler.post(new Runnable() { @Override public void run() { adapterPrepareListener.onReadyAdapter(month, monthDays, monthInfoDto.recyclerView); } }); } private List<Calendar> prepare(Calendar monthCalendar) { List<Calendar> monthDays = new ArrayList<>(); Calendar iterator = (Calendar) monthCalendar.clone(); int month = iterator.get(Calendar.MONTH); int lastDay = iterator.getActualMaximum(Calendar.DATE); iterator.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); if (iterator.get(Calendar.MONTH) == month && iterator.get(Calendar.DATE) > 1) { iterator.add(Calendar.DATE, -7); } boolean finish = false; while (!finish) { for (int i = 0; i < NUM_OF_DAYS_IN_WEEK; i++) { if (month == iterator.get(Calendar.MONTH) && lastDay == iterator.get(Calendar.DATE)) { finish = true; } monthDays.add((Calendar) iterator.clone()); iterator.add(Calendar.DATE, 1); } } return monthDays; } }