misc improvements
* don't show notifications while download activity * proper icon in failed download notifications * re-write list auto-refresh (MissionAdapter.java) * improve I/O performance (CircularFile.java) * fix implementation of "save thread position" on multi-thread downloads
This commit is contained in:
parent
6d4e97a877
commit
db0c4642a4
11 changed files with 270 additions and 184 deletions
|
|
@ -20,6 +20,7 @@ import android.support.v7.app.AlertDialog;
|
|||
import android.support.v7.util.DiffUtil;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.support.v7.widget.RecyclerView.Adapter;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
|
|
@ -40,7 +41,6 @@ import org.schabi.newpipe.util.NavigationHelper;
|
|||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import us.shandian.giga.get.DownloadMission;
|
||||
import us.shandian.giga.get.FinishedMission;
|
||||
|
|
@ -53,9 +53,10 @@ import us.shandian.giga.util.Utility;
|
|||
import static android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
|
||||
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
||||
|
||||
public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
||||
public class MissionAdapter extends Adapter<ViewHolder> {
|
||||
private static final SparseArray<String> ALGORITHMS = new SparseArray<>();
|
||||
private static final String TAG = "MissionAdapter";
|
||||
private static final String UNDEFINED_SPEED = "--.-%";
|
||||
|
||||
static {
|
||||
ALGORITHMS.put(R.id.md5, "MD5");
|
||||
|
|
@ -89,6 +90,7 @@ public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
case DownloadManagerService.MESSAGE_ERROR:
|
||||
case DownloadManagerService.MESSAGE_FINISHED:
|
||||
onServiceMessage(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -120,7 +122,10 @@ public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
if (view instanceof ViewHolderHeader) return;
|
||||
ViewHolderItem h = (ViewHolderItem) view;
|
||||
|
||||
if (h.item.mission instanceof DownloadMission) mPendingDownloadsItems.remove(h);
|
||||
if (h.item.mission instanceof DownloadMission) {
|
||||
mPendingDownloadsItems.remove(h);
|
||||
if (mPendingDownloadsItems.size() < 1) setAutoRefresh(false);
|
||||
}
|
||||
|
||||
h.popupMenu.dismiss();
|
||||
h.item = null;
|
||||
|
|
@ -153,10 +158,11 @@ public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
h.item = item;
|
||||
|
||||
Utility.FileType type = Utility.getFileType(item.mission.kind, item.mission.name);
|
||||
long length = item.mission instanceof FinishedMission ? item.mission.length : ((DownloadMission) item.mission).getLength();
|
||||
|
||||
h.icon.setImageResource(Utility.getIconForFileType(type));
|
||||
h.name.setText(item.mission.name);
|
||||
h.size.setText(Utility.formatBytes(item.mission.length));
|
||||
h.size.setText(Utility.formatBytes(length));
|
||||
|
||||
h.progress.setColors(Utility.getBackgroundForFileType(mContext, type), Utility.getForegroundForFileType(mContext, type));
|
||||
|
||||
|
|
@ -187,66 +193,60 @@ public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
private void updateProgress(ViewHolderItem h) {
|
||||
if (h == null || h.item == null || h.item.mission instanceof FinishedMission) return;
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
DownloadMission mission = (DownloadMission) h.item.mission;
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (h.lastTimeStamp == -1) {
|
||||
h.lastTimeStamp = now;
|
||||
}
|
||||
|
||||
if (h.lastDone == -1) {
|
||||
h.lastDone = mission.done;
|
||||
}
|
||||
if (h.lastCurrent != mission.current) {
|
||||
h.lastCurrent = mission.current;
|
||||
h.lastDone = 0;
|
||||
h.lastTimeStamp = now;
|
||||
h.lastDone = 0;
|
||||
} else {
|
||||
if (h.lastTimeStamp == -1) h.lastTimeStamp = now;
|
||||
if (h.lastDone == -1) h.lastDone = mission.done;
|
||||
}
|
||||
|
||||
long deltaTime = now - h.lastTimeStamp;
|
||||
long deltaDone = mission.done - h.lastDone;
|
||||
boolean hasError = mission.errCode != DownloadMission.ERROR_NOTHING;
|
||||
|
||||
if (hasError || deltaTime == 0 || deltaTime > 1000) {
|
||||
// on error hide marquee or show if condition (mission.done < 1 || mission.unknownLength) is true
|
||||
h.progress.setMarquee(!hasError && (mission.done < 1 || mission.unknownLength));
|
||||
// on error hide marquee or show if condition (mission.done < 1 || mission.unknownLength) is true
|
||||
h.progress.setMarquee(!hasError && (mission.done < 1 || mission.unknownLength));
|
||||
|
||||
float progress;
|
||||
if (mission.unknownLength) {
|
||||
progress = Float.NaN;
|
||||
h.progress.setProgress(0f);
|
||||
} else {
|
||||
progress = (float) ((double) mission.done / mission.length);
|
||||
if (mission.urls.length > 1 && mission.current < mission.urls.length) {
|
||||
progress = (progress / mission.urls.length) + ((float) mission.current / mission.urls.length);
|
||||
}
|
||||
float progress;
|
||||
if (mission.unknownLength) {
|
||||
progress = Float.NaN;
|
||||
h.progress.setProgress(0f);
|
||||
} else {
|
||||
progress = (float) ((double) mission.done / mission.length);
|
||||
if (mission.urls.length > 1 && mission.current < mission.urls.length) {
|
||||
progress = (progress / mission.urls.length) + ((float) mission.current / mission.urls.length);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasError) {
|
||||
if (Float.isNaN(progress) || Float.isInfinite(progress))
|
||||
h.progress.setProgress(1f);
|
||||
h.status.setText(R.string.msg_error);
|
||||
} else if (Float.isNaN(progress) || Float.isInfinite(progress)) {
|
||||
h.status.setText("--.-%");
|
||||
} else {
|
||||
h.status.setText(String.format("%.2f%%", progress * 100));
|
||||
h.progress.setProgress(progress);
|
||||
}
|
||||
if (hasError) {
|
||||
if (Float.isNaN(progress) || Float.isInfinite(progress))
|
||||
h.progress.setProgress(1f);
|
||||
h.status.setText(R.string.msg_error);
|
||||
} else if (Float.isNaN(progress) || Float.isInfinite(progress)) {
|
||||
h.status.setText(UNDEFINED_SPEED);
|
||||
} else {
|
||||
h.status.setText(String.format("%.2f%%", progress * 100));
|
||||
h.progress.setProgress(progress);
|
||||
}
|
||||
|
||||
long length = mission.getLength();
|
||||
|
||||
int state = 0;
|
||||
if (!mission.isFinished()) {
|
||||
if (!mission.running) {
|
||||
state = mission.enqueued ? 1 : 2;
|
||||
} else if (mission.postprocessingRunning) {
|
||||
state = 3;
|
||||
}
|
||||
int state;
|
||||
if (!mission.running) {
|
||||
state = mission.enqueued ? 1 : 2;
|
||||
} else if (mission.postprocessingRunning) {
|
||||
state = 3;
|
||||
} else {
|
||||
state = 0;
|
||||
}
|
||||
|
||||
if (state != 0) {
|
||||
// update state without download speed
|
||||
if (h.state != state) {
|
||||
String statusStr;
|
||||
h.state = state;
|
||||
|
|
@ -267,7 +267,7 @@ public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
}
|
||||
|
||||
h.size.setText(Utility.formatBytes(length).concat(" (").concat(statusStr).concat(")"));
|
||||
} else if (deltaTime > 1000 && deltaDone > 0) {
|
||||
} else if (deltaDone > 0) {
|
||||
h.lastTimeStamp = now;
|
||||
h.lastDone = mission.done;
|
||||
}
|
||||
|
|
@ -275,10 +275,10 @@ public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
return;
|
||||
}
|
||||
|
||||
if (deltaDone > 0 && deltaTime > 0) {
|
||||
float speed = (deltaDone * 1000f) / deltaTime;
|
||||
|
||||
if (deltaTime > 1000 && deltaDone > 0) {
|
||||
float speed = (float) ((double) deltaDone / deltaTime);
|
||||
String speedStr = Utility.formatSpeed(speed * 1000);
|
||||
String speedStr = Utility.formatSpeed(speed);
|
||||
String sizeStr = Utility.formatBytes(length);
|
||||
|
||||
h.size.setText(sizeStr.concat(" ").concat(speedStr));
|
||||
|
|
@ -325,6 +325,8 @@ public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
private void onServiceMessage(@NonNull Message msg) {
|
||||
switch (msg.what) {
|
||||
case DownloadManagerService.MESSAGE_PROGRESS:
|
||||
setAutoRefresh(true);
|
||||
return;
|
||||
case DownloadManagerService.MESSAGE_ERROR:
|
||||
case DownloadManagerService.MESSAGE_FINISHED:
|
||||
break;
|
||||
|
|
@ -339,8 +341,6 @@ public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
if (msg.what == DownloadManagerService.MESSAGE_FINISHED) {
|
||||
// DownloadManager should mark the download as finished
|
||||
applyChanges();
|
||||
|
||||
mPendingDownloadsItems.remove(i);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -396,7 +396,9 @@ public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
break;
|
||||
default:
|
||||
if (mission.errCode >= 100 && mission.errCode < 600) {
|
||||
str.append("HTTP");
|
||||
str = new StringBuilder(8);
|
||||
str.append("HTTP ");
|
||||
str.append(mission.errCode);
|
||||
} else if (mission.errObject == null) {
|
||||
str.append("(not_decelerated_error_code)");
|
||||
}
|
||||
|
|
@ -436,7 +438,7 @@ public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
case R.id.pause:
|
||||
h.state = -1;
|
||||
mDownloadManager.pauseMission(mission);
|
||||
notifyItemChanged(h.getAdapterPosition());
|
||||
updateProgress(h);
|
||||
h.lastTimeStamp = -1;
|
||||
h.lastDone = -1;
|
||||
return true;
|
||||
|
|
@ -542,6 +544,43 @@ public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
}
|
||||
|
||||
|
||||
private boolean mUpdaterRunning = false;
|
||||
private final Runnable rUpdater = this::updater;
|
||||
|
||||
public void onPaused() {
|
||||
setAutoRefresh(false);
|
||||
}
|
||||
|
||||
private void setAutoRefresh(boolean enabled) {
|
||||
if (enabled && !mUpdaterRunning) {
|
||||
mUpdaterRunning = true;
|
||||
updater();
|
||||
} else if (!enabled && mUpdaterRunning) {
|
||||
mUpdaterRunning = false;
|
||||
mHandler.removeCallbacks(rUpdater);
|
||||
}
|
||||
}
|
||||
|
||||
private void updater() {
|
||||
if (!mUpdaterRunning) return;
|
||||
|
||||
boolean running = false;
|
||||
for (ViewHolderItem h : mPendingDownloadsItems) {
|
||||
// check if the mission is running first
|
||||
if (!((DownloadMission) h.item.mission).running) continue;
|
||||
|
||||
updateProgress(h);
|
||||
running = true;
|
||||
}
|
||||
|
||||
if (running) {
|
||||
mHandler.postDelayed(rUpdater, 1000);
|
||||
} else {
|
||||
mUpdaterRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ViewHolderItem extends RecyclerView.ViewHolder {
|
||||
DownloadManager.MissionItem item;
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public class MissionsFragment extends Fragment {
|
|||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder binder) {
|
||||
mBinder = (DownloadManagerService.DMBinder) binder;
|
||||
mBinder.resetFinishedDownloadCount();
|
||||
mBinder.clearDownloadNotifications();
|
||||
|
||||
mAdapter = new MissionAdapter(mActivity, mBinder.getDownloadManager(), mClear, mEmpty);
|
||||
mAdapter.deleterLoad(mBundle, getView());
|
||||
|
|
@ -59,6 +59,7 @@ public class MissionsFragment extends Fragment {
|
|||
mBundle = null;
|
||||
|
||||
mBinder.addMissionEventListener(mAdapter.getMessenger());
|
||||
mBinder.enableNotifications(false);
|
||||
|
||||
updateList();
|
||||
}
|
||||
|
|
@ -130,7 +131,7 @@ public class MissionsFragment extends Fragment {
|
|||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
|
|
@ -141,6 +142,7 @@ public class MissionsFragment extends Fragment {
|
|||
if (mBinder == null || mAdapter == null) return;
|
||||
|
||||
mBinder.removeMissionEventListener(mAdapter.getMessenger());
|
||||
mBinder.enableNotifications(true);
|
||||
mActivity.unbindService(mConnection);
|
||||
mAdapter.deleterDispose(null);
|
||||
|
||||
|
|
@ -181,7 +183,7 @@ public class MissionsFragment extends Fragment {
|
|||
// destroy all created views in the recycler
|
||||
mList.setAdapter(null);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
|
||||
|
||||
// re-attach the adapter in grid/lineal mode
|
||||
mAdapter.setLinear(mLinear);
|
||||
mList.setAdapter(mAdapter);
|
||||
|
|
@ -201,14 +203,13 @@ public class MissionsFragment extends Fragment {
|
|||
mAdapter.deleterDispose(outState);
|
||||
mForceUpdate = true;
|
||||
mBinder.removeMissionEventListener(mAdapter.getMessenger());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
|
||||
if (mAdapter != null) {
|
||||
mAdapter.deleterResume();
|
||||
|
||||
|
|
@ -219,5 +220,13 @@ public class MissionsFragment extends Fragment {
|
|||
|
||||
mBinder.addMissionEventListener(mAdapter.getMessenger());
|
||||
}
|
||||
if (mBinder != null) mBinder.enableNotifications(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (mAdapter != null) mAdapter.onPaused();
|
||||
if (mBinder != null) mBinder.enableNotifications(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue