Подтвердить что ты не робот

ParseFile.cancel() не работает - файл продолжает загружаться

Я использую 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.
4b9b3361

Ответ 1

Похоже, что это была настоящая ошибка, теперь исправленная. Раньше я оставался с релизом v1.9.2; сегодня я обновился до v1.10.0, и все работает нормально.

Ответ 2

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 никогда не называется, хотя он говорит, что он гарантирован. Тем не менее, по-прежнему кажется, что отмена работает на меня.