164 lines
4.4 KiB
Java
164 lines
4.4 KiB
Java
package com.thebrokenrail.mtudining.activity.task;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
import com.thebrokenrail.mtudining.widget.LoaderView;
|
|
|
|
/**
|
|
* RecyclerView adapter for a given {@link Task}.
|
|
*/
|
|
public abstract class TaskAdapter<E, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Task.Listener<E> {
|
|
public static final int LOADER_TYPE = 1;
|
|
public static final int DATA_TYPE = 0;
|
|
|
|
/**
|
|
* The task.
|
|
*/
|
|
private final Task<E> task;
|
|
|
|
/**
|
|
* Current task status.
|
|
*/
|
|
private Task.Status currentStatus;
|
|
|
|
/**
|
|
* Task result (or null if none).
|
|
*/
|
|
private E result;
|
|
|
|
/**
|
|
* Get task result.
|
|
* @return Task result
|
|
*/
|
|
protected E getResult() {
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Create adapter.
|
|
* @param task The task
|
|
*/
|
|
public TaskAdapter(Task<E> task) {
|
|
// Setup Event Handling
|
|
this.task = task;
|
|
task.addListener(this);
|
|
}
|
|
|
|
/**
|
|
* Call when activity is destroyed.
|
|
*/
|
|
public void onDestroy() {
|
|
// Stop Handling Events
|
|
task.removeListener(this);
|
|
}
|
|
|
|
/**
|
|
* Create view holder for item in task's result.
|
|
* @param parent The view parent
|
|
* @return The new view holder
|
|
*/
|
|
protected abstract VH createItemViewHolder(@NonNull ViewGroup parent);
|
|
|
|
@NonNull
|
|
@Override
|
|
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
if (viewType == LOADER_TYPE) {
|
|
// Loader
|
|
LoaderView loader = new LoaderView(parent.getContext(), null);
|
|
RecyclerView.LayoutParams layoutParams = new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT);
|
|
loader.setLayoutParams(layoutParams);
|
|
return new RecyclerView.ViewHolder(loader) {};
|
|
} else if (viewType == DATA_TYPE) {
|
|
// Data
|
|
return createItemViewHolder(parent);
|
|
} else {
|
|
// Unknown
|
|
throw new RuntimeException();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bind view holder for item in task's result.
|
|
* @param holder The view holder
|
|
* @param position The item's position
|
|
*/
|
|
protected abstract void bindDataViewHolder(@NonNull VH holder, int position);
|
|
|
|
@SuppressWarnings({"unchecked"})
|
|
@Override
|
|
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
|
int type = getItemViewType(position);
|
|
if (type == LOADER_TYPE) {
|
|
// Loader
|
|
((LoaderView) holder.itemView).setup(currentStatus == Task.Status.ERROR, task::start);
|
|
} else if (type == DATA_TYPE) {
|
|
// Data
|
|
bindDataViewHolder((VH) holder, position);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get size of task's dataset.
|
|
* @return The size of the dataset
|
|
*/
|
|
protected abstract int getDataSize();
|
|
|
|
@Override
|
|
public int getItemCount() {
|
|
if (currentStatus != Task.Status.DONE) {
|
|
// Only Loader
|
|
return 1;
|
|
} else {
|
|
// Data Size
|
|
return getDataSize();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getItemViewType(int position) {
|
|
if (currentStatus != Task.Status.DONE && position == 0) {
|
|
// Loader
|
|
return LOADER_TYPE;
|
|
} else {
|
|
// Data
|
|
return DATA_TYPE;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void update(Task.Status status, E result) {
|
|
int oldItemCount = getItemCount();
|
|
// Store
|
|
this.currentStatus = status;
|
|
this.result = result;
|
|
// Change UI
|
|
if (status == Task.Status.IN_PROGRESS || status == Task.Status.NOT_STARTED) {
|
|
// Show Progress Circle
|
|
reloadUI(oldItemCount);
|
|
// Start Task If Needed
|
|
if (status == Task.Status.NOT_STARTED) {
|
|
task.start();
|
|
}
|
|
} else if (status == Task.Status.ERROR) {
|
|
// Show Error
|
|
reloadUI(oldItemCount);
|
|
} else {
|
|
// Done
|
|
reloadUI(oldItemCount);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reload UI.
|
|
*/
|
|
private void reloadUI(int oldItemCount) {
|
|
// Remove Existing Items
|
|
notifyItemRangeRemoved(0, oldItemCount);
|
|
// Add Items
|
|
notifyItemRangeInserted(0, getItemCount());
|
|
}
|
|
}
|