我有一点问题,我想这很容易解决。但我现在真的没有得到解决方案。
我有一个IntentService,它显示实际下载文件的状态,并填入ListView子级。那里的一切都很好。
改编自此处:Download multiple files with a progress bar in ListView Android
但是一旦我想要删除已启动的下载,因为它变得不必要了。我的问题发生了。 我无法停止IntenService。
我尝试了不同的方法。
How to force an IntentService to stop immediately with a cancel button from an Activity?
How to stop intentservice in android?
目前我正在向DownloadTask发送一个假信号,这意味着下载成功了。
public static void removeItems(){
startup--;
Log.e("Button", "clicked" + "position " + global_position);
//tasks contains all DownloadTasks
//**sending fake signal here**
DownloadingService.DownloadTask t = tasks.get(global_position);
t.mProgress = 101;
a.remove(global_position); //remove Progress Array_List
tasks.remove(global_position); //remove DownloadTask
//update the UI
listView.setAdapter(mAdapter = new ArrayAdapter<Progress>(act, R.layout.progressbar_list, R.id.textView, a){
});
//trying to stop the IntentService, but goes to the wrong Thread
act.stopService(intent);
intent = new Intent(act, DownloadingService.class);
intent.putExtra("files", mAdapter.getCount());
if(tasks.size() > 0) {
//startService causes crash
//act.startService(intent);
}
}
这样可以正常工作,但前提是ListView中只有一个子节点。 DownloadTask完成,IntentService停止。但是只要ListView中有更多子节点,调用就不会完成下载并且IntentService会继续滚动。这导致了NullPointer,因为它想要填充我已经删除的ListView子项。
我的下载服务:
public static class DownloadingService extends IntentService {
public static String PROGRESS_UPDATE_ACTION = DownloadingService.class
.getName() + ".progress_update";
private ExecutorService mExec;
private CompletionService<NoResultType> mEcs;
private LocalBroadcastManager mBroadcastManager;
private ArrayList<DownloadTask> mTasks;
public static volatile boolean shouldContinue = true;
private static final long INTERVAL_BROADCAST = 800;
private long mLastUpdate = 0;
public DownloadingService() {
super("DownloadingService");
Log.e("DOWNLOADING", "SERVICE");
mExec = Executors.newFixedThreadPool(20);
mEcs = new ExecutorCompletionService<NoResultType>(mExec);
mBroadcastManager = LocalBroadcastManager.getInstance(this);
mTasks = new ArrayList<Uebersicht.DownloadingService.DownloadTask>();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
protected void onHandleIntent(Intent intent) {
doStuff();
if(startup <= 1) {
Log.e("startup", "<1" + startup);
tasks = mTasks;
noOfFilesToDownalod = 0;
Log.e("filestodownload", " " + noOfFilesToDownalod);
DownloadTask yt1 = new DownloadTask(noOfFilesToDownalod);
tasks.add(yt1);
Log.e("TASKS", " " + tasks.size());
for (DownloadTask t : tasks) {
mEcs.submit(t);
}
// wait for finish
int n = tasks.size();
for (int i = 0; i < n; ++i) {
NoResultType r;
try {
r = mEcs.take().get();
if (r != null) {
// use you result here
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
// send a last broadcast
publishCurrentProgressOneShot(true);
mExec.shutdown();
}else {
Log.e("startup", "elsee" + startup);
noOfFilesToDownalod++;
Log.e("noOFiles", " " + noOfFilesToDownalod);
//noOfFilesToDownalod = intent.getIntExtra("files", 0);
tasks.add(new DownloadTask(noOfFilesToDownalod));
Log.e(" tasks", ""+ tasks.size());
DownloadTask t = new DownloadTask(noOfFilesToDownalod);
mEcs.submit(t);
int n = tasks.size();
for (int i = 0; i < n; ++i) {
NoResultType r;
try {
r = mEcs.take().get();
if (r != null) {
// use you result here
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
// send a last broadcast
publishCurrentProgressOneShot(true);
mExec.shutdown();
}
}
private void doStuff(){
if (!shouldContinue) {
stopSelf();
Log.e("stopped?", "yeah");
return;
}
}
private void publishCurrentProgressOneShot(boolean forced) {
if (forced
|| System.currentTimeMillis() - mLastUpdate > INTERVAL_BROADCAST) {
mLastUpdate = System.currentTimeMillis();
final List<DownloadTask> taskspublish = mTasks;
int[] positions = new int[taskspublish.size()];
int[] progresses = new int[taskspublish.size()];
int[] times = new int[taskspublish.size()];
for (int i = 0; i < taskspublish.size(); i++) {
DownloadTask t = taskspublish.get(i);
positions[i] = t.mPosition;
progresses[i] = round(t.mProgress);
times[i] = t.minutesleft;
}
publishProgress(positions, progresses, times);
}
}
private int round(double d){
double dAbs = Math.abs(d);
int i = (int) dAbs;
double result = dAbs - (double) i;
if(result<0.5){
return d<0 ? -i : i;
}else{
return d<0 ? -(i+1) : i+1;
}
}
private void publishCurrentProgressOneShot() {
publishCurrentProgressOneShot(false);
}
private synchronized void publishProgress(int[] positions,
int[] progresses, int[] times) {
Intent i = new Intent();
i.setAction(PROGRESS_UPDATE_ACTION);
i.putExtra("position", positions);
i.putExtra("progress", progresses);
i.putExtra("time", times);
i.putExtra("oneshot", true);
mBroadcastManager.sendBroadcast(i);
}
class DownloadTask implements Callable<NoResultType> {
private int mPosition;
private double mProgress = (100 * Menge.getGroesse()) / 50;
private double rateinsek = Menge.getRate() / 60 / 60;
private double mlprosek = (rateinsek * Menge.getRate()) / Menge.getGroesse();
private int count = 0;
private double ratepromin = Menge.getRate() / 60;
private double left = Menge.getGroesse() / ratepromin;
private int minutesleft = (int) left;
public DownloadTask(int position) {
mPosition = position;
}
@Override
public NoResultType call() throws Exception {
while (mProgress > 0) {
mProgress -= mlprosek;
Log.e("MPROGRESS", " " + mProgress);
Thread.sleep(1000);
count++;
if(count == 60){
minutesleft = minutesleft-1;
Log.e("COUNT", "-1");
count = 0;
}
// publish progress
publishCurrentProgressOneShot();
// we can also call publishProgress(int position, int
// progress) instead, which will work fine but avoid broadcasts
// by aggregating them
//publishProgress(mPosition,mProgress);
}
return new NoResultType();
}
public double getProgress() {
return mProgress;
}
public int getPosition() {
return mPosition;
}
}
class NoResultType {
NoResultType(){
Log.e("READY", "100 %");
}
}
}
答案 0 :(得分:0)
问题很容易解决。我刚刚在DownloadTask中为while循环添加了一个额外的参数。
将ListView中单击的位置与ListView中的DownloadTask的位置进行比较。
一旦两个位置相同,下载就会停止。
while (mProgress > 0 && global_position != mPosition) {
mProgress -= mlprosek;
Log.e("MPROGRESS", " " + mProgress + " timeleft " + minutesleft);
Thread.sleep(1000);
count++;
if(count == 60){
minutesleft = minutesleft-1;
Log.e("COUNT", "-1");
count = 0;
}