Ответ 1
Похоже, что это была настоящая ошибка, теперь исправленная. Раньше я оставался с релизом v1.9.2
; сегодня я обновился до v1.10.0
, и все работает нормально.
Я использую parse.com
Android SDK для управления некоторыми изображениями в своем приложении. Является ли cancel()
единственным способом остановить транзакцию с сервером parse.com
?
Минимальный пример:
final ParseFile file = ... ;
file.getDataInBackground(new GetDataCallback() {
//called when loading is done
@Override
public void done(byte[] bytes, ParseException e) {
Log.e(TAG, String.valueOf(bytes == null));
}
}, new ProgressCallback() {
//called to notify progress
@Override
public void done(Integer integer) {
Log.e(TAG, String.valueOf(integer));
if (integer > 50) {
file.cancel();
}
}
});
Я бы ожидал, что загрузка остановится после достижения 50%, но это не так. Мой журнал в этой ситуации:
1
2
3
....
49
50
51
....
98
99
100
true
Единственное отличие от времени, которое вы вызываете cancel()
, а не в случае, если вы отменили результат byte[]
, равен нулю. Но это действительно второстепенно, дело в том, что file
продолжает потреблять полосу пропускания и, более того, накладывается на будущие загрузки, замедляя работу.
Есть ли способ остановить загрузку ParseFile? Вы видите какое-нибудь обходное решение, например, прекращение его потока? Может быть, что-то использует базовые рамки болтов? Использование моей собственной задачи async?
Пример: continueWhile()
метод может быть полезен, но я не могу понять, как его использовать.
Я хотел бы знать причину нисходящего, возможно, общего названия? Это действительно то, что я испытываю: ParseFile.cancel() не работает. И это должно, согласно официальному docs.
Комментарии предполагают, что я должен просто вызвать break
. Хотя я не думаю, что это сработает, я могу уточнить, что код, который я опубликовал, был минимальным, сжатым рабочим примером, обеспечивающим как контекст, так и проблему. Я не хочу cancel()
транзакции изнутри обратного вызова прогресса; Я хочу называть parseFile.cancel()
всюду. Я включил обратный вызов, чтобы показать, что, хотя он должен остановиться, это не так.
Изменить Это то, что я действительно пытаюсь сделать. Я пробовал разные способы, но это все.
ParseFile currentFile;
public void setFile(ParseFile file) {
if (currentFile != null) {
currentFile.cancel();
}
currentFile = file;
currentFile.getDataInBackground(new GetDataCallback() {
...
}, new ProgressCallback() {
... // logs
});
}
С таким кодом и скажем, два больших изображения для загрузки, все идет так:
//calling setFile(file1)
1
2
3
...
20
21
22
//calling setFile(file2), thus also calling file1.cancel()
1
2
23 //file1 going on!
3
24
4
25
... //things get slower and this screws up progress bars and such.
Похоже, что это была настоящая ошибка, теперь исправленная. Раньше я оставался с релизом v1.9.2
; сегодня я обновился до v1.10.0
, и все работает нормально.
TL; DR;
Единственный вывод, который я могу сделать на этом этапе, состоит в том, что есть разница в наших реализациях, которые вызывают откат для вас.
EDIT: похоже, это так, как видно из вашего собственного ответа. Разница заключается в версиях SDK. fooobar.com/info/454296/...
Полный ответ:
Описание метода cancel()
:
"Отменяет текущий сетевой запрос и обратные вызовы, загружает или извлекает данные с сервера.
Мне было любопытно об этом, поэтому я сделал небольшое тестирование. Я взял свое приложение, сделал ParseFile
из байтов изображения и попытался сохранить его в фоновом режиме.
Тест 1
Bitmap file = BitmapFactory.decodeResource(context.getResources(), R.drawable.background);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
file.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
final ParseFile myTestFile = new ParseFile(byteArray);
myTestFile.saveInBackground(new SaveCallback(){
@Override
public void done(ParseException e) {
if(e == null)
{
Log.i(null, "Done saving.");
}
}
}, new ProgressCallback(){
@Override
public void done(Integer progress) {
Log.i(null, "Progress at " + progress + "%");
if(progress > 50)
{
myTestFile.cancel();
}
}});
//myTestFile.cancel();
Тест 2
Bitmap file = BitmapFactory.decodeResource(context.getResources(), R.drawable.background);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
file.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
ParseFile myTestFile = new ParseFile(byteArray);
myTestFile.saveInBackground(new SaveCallback(){
@Override
public void done(ParseException e) {
if(e == null)
{
Log.i(null, "Done saving.");
}
}
}, new ProgressCallback(){
@Override
public void done(Integer progress) {
Log.i(null, "Progress at " + progress + "%");
}});
myTestFile.cancel();
Результаты теста 1 были похожи на то, что вы описываете, потому что файл очень маленький. Я получил только один обратный вызов прогресса на 100%, но затем он также вызвал SaveCallback
.
Однако в тесте 2 метод cancel()
функционирует так, как можно было бы ожидать, в результате чего не было бы журналов или обратных вызовов.
Похоже, что отмена не работает, потому что вы вызываете ее из Callback. Это согласуется с тем фактом, что вы продолжаете видеть ProgressCallbacks после первоначального аннулирования в своих собственных тестах.
ИЗМЕНИТЬ
Я просто загрузил изображение и протестировал отмену для себя, в методе onCreate() моей активности. У меня есть этот код:
ParseQuery<ParseObject> newQuery = ParseQuery.getQuery("TestObject");
newQuery.findInBackground(new FindCallback<ParseObject>(){
@Override
public void done(List<ParseObject> objects, ParseException e)
{
ParseFile myTestFile = objects.get(0).getParseFile("file");
myTestFile.getDataInBackground(new GetDataCallback()
{
@Override
public void done(byte[] data, ParseException e)
{
Log.i(null, "Download finished");
}
},
new ProgressCallback()
{
@Override
public void done(Integer percentDone)
{
Log.i(null, "Download at " + percentDone + "%");
}
});
//myTestFile.cancel();
}});
Когда отмена прокомментирована, она войдет в GetDataCallback с заполненным массивом байтов. Если отмена не прокомментирована, вызов не будет выполнен. Как ни странно, ProgressCallback никогда не называется, хотя он говорит, что он гарантирован. Тем не менее, по-прежнему кажется, что отмена работает на меня.