我正在使用IntentService从列表中下载200个大型JPG。在加载时,用户可以跳过未加载的JPG并加载JPG#156,但是在加载之后,它应该继续加载其余的JPG。所以它就像一个懒惰的装载机......但是当它闲置时它会继续。
我之前使用过onHandleIntent并从#1到#200循环...当我尝试为JPG#156发送另一个IntentService调用时,这显然不起作用。所以对#156的调用只发生在onHandleIntent完成#200。
之后然后我更改了它,因此onHandleIntent重新排序请求#156位于列表的顶部,然后请求列表的顶部(并下载JPG),然后将其从列表中删除。然后它再次调用IntentService,这听起来像递归/堆栈溢出有点冒险。它有时候工作,我可以看到文件#156被放在第一位......有时候。
有更好的方法吗?我能想到的一种方法是通过数据库运行它。
编辑:这就是我的想法: code
public class PBQDownloader extends IntentService {
int currentWeight = 0;
PriorityBlockingQueue<WeightedAsset> pbQueue = new PriorityBlockingQueue<WeightedAsset>(100, new CompareWeightedAsset());
public PBQDownloader() {
super("PBQDownloader");
}
public PBQDownloader(String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
String downloadUrl = "-NULL-";
Bundle extras = intent.getExtras();
if (extras!=null) {
downloadUrl = extras.getString("url");
Log.d("onHandleIntent 1.1", "asked to download: " + downloadUrl);
} else {
Log.d("onHandleIntent 1.2", "no URL sent so let's start queueing everything");
int MAX = 10;
for (int i = 1; i <= MAX; i++) {
// should read URLs from list
WeightedAsset waToAdd = new WeightedAsset("url: " + i, MAX - i);
if (pbQueue.contains(waToAdd)) {
Log.d("onStartCommand 1", downloadUrl + " already exists, so we are removing it and adding it back with a new priority");
pbQueue.remove(waToAdd);
}
pbQueue.put(waToAdd);
}
currentWeight = MAX + 1;
}
while (!pbQueue.isEmpty()) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
WeightedAsset waToProcess = pbQueue.poll();
Log.d("onHandleIntent 2 DOWNLOADED", waToProcess.url);
}
Log.d("onHandleIntent 99", "finished all IntentService calls");
}
@Override
public int onStartCommand(Intent intent, int a, int b) {
super.onStartCommand(intent, a, b);
currentWeight++;
String downloadUrl = "-NULL-";
Bundle extras = intent.getExtras();
if (extras!=null) downloadUrl = extras.getString("url");
Log.d("onStartCommand 0", "download: " + downloadUrl + " with current weight: " + currentWeight);
WeightedAsset waToAdd = new WeightedAsset(downloadUrl, currentWeight);
if (pbQueue.contains(waToAdd)) {
Log.d("onStartCommand 1", downloadUrl + " already exists, so we are removing it and adding it back with a new priority");
pbQueue.remove(waToAdd);
}
pbQueue.put(waToAdd);
return 0;
}
private class CompareWeightedAsset implements Comparator<WeightedAsset> {
@Override
public int compare(WeightedAsset a, WeightedAsset b) {
if (a.weight < b.weight) return 1;
if (a.weight > b.weight) return -1;
return 0;
}
}
private class WeightedAsset {
String url;
int weight;
public WeightedAsset(String u, int w) {
url = u;
weight = w;
}
}
}
code
然后我有这个活动:
code
public class HelloPBQ extends Activity {
int sCount = 10;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button tv01 = (Button) findViewById(R.id.tv01);
Button tv02 = (Button) findViewById(R.id.tv02);
Button tv03 = (Button) findViewById(R.id.tv03);
tv01.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
doPBQ();
}
});
tv02.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
doInitPBQ();
}
});
tv03.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
sCount = 0;
}
});
}
private void doInitPBQ() {
Intent intent = new Intent(getApplicationContext(), PBQDownloader.class);
//intent.putExtra("url", "url: " + sCount);
startService(intent);
}
private void doPBQ() {
sCount++;
Intent intent = new Intent(getApplicationContext(), PBQDownloader.class);
intent.putExtra("url", "url: " + sCount);
startService(intent);
}
}
code
现在凌乱的是,我必须保持一个不断增加的计数器,冒着走出int界限的风险(WeightedAsset.weight) - 有没有办法以编程方式添加到队列并让它自动成为队长?我试图用一个字符串替换WeightedAsset,但它没有像我想要的那样poll(),而不是一个FIFO而不是LIFO堆栈。
答案 0 :(得分:2)
以下是我首先尝试的方法:
步骤1:让IntentService
抓住PriorityBlockingQueue
。
步骤2:让onHandleIntent()
遍历PriorityBlockingQueue
,在队列弹出时依次下载每个文件。
步骤#3:让onStartCommand()
查看命令是否是“启动所有下载”命令(在这种情况下,链接到超类)。相反,如果是“优先处理此下载”命令,请在PriorityBlockingQueue
中重新确定该条目的优先顺序,以便在当前下载完成后,onHandleIntent()
接下来选择该条目。