web-dev-qa-db-fra.com

Android Retrofit - onProgressUpdate pour afficher la notification de progression

J'utilise actuellement Retrofit by Square pour les communications réseau Android. Existe-t-il un moyen d'obtenir sa progression pendant une tâche pour créer une notification de progression, quelque chose de similaire à celui utilisé par Facebook lors du téléchargement d'une image ?

Le cas d'utilisation serait de charger une image, espérons-le, de qualité d'image complète sans compression ni mise à l'échelle.

Je vois comment c'est possible avec une asynctask mais cela irait à l'encontre du but de l'utilisation de Retrofit. Cependant, cela pourrait être la voie que je devrais emprunter.

37
John Shelley

Cette réponse est pour Retrofit 1. Pour une solution compatible avec Retrofit 2 voir cette réponse .


J'ai eu le même problème et j'ai finalement réussi à le faire. J'utilisais Spring Lib avant et ce que je montre ci-dessous fonctionnait pour Spring mais n'était pas cohérent car j'ai fait une erreur en l'utilisant pour InputStream. J'ai déplacé toutes mes API pour utiliser la modification et le téléchargement était le dernier de la liste, je remplace simplement TypedFile writeTo () pour me mettre à jour sur les octets lus au OutputStream. Peut-être que cela peut être amélioré, mais comme je l'ai dit, je l'ai fait lorsque j'utilisais Spring, donc je l'ai simplement réutilisé. C'est le code pour le téléchargement et cela fonctionne pour moi sur mon application, si vous voulez des commentaires sur le téléchargement, vous pouvez utiliser @Streaming et lire le inputStream.

ProgressListener

public interface ProgressListener {
 void transferred(long num);
}

CountingTypedFile

public class CountingTypedFile extends TypedFile {

 private static final int BUFFER_SIZE = 4096;

 private final ProgressListener listener;

 public CountingTypedFile(String mimeType, File file, ProgressListener listener) {
    super(mimeType, file);
    this.listener = listener;
 }

 @Override public void writeTo(OutputStream out) throws IOException {
    byte[] buffer = new byte[BUFFER_SIZE];
    FileInputStream in = new FileInputStream(super.file());
    long total = 0;
    try {
        int read;
        while ((read = in.read(buffer)) != -1) {
            total += read;
            this.listener.transferred(total);
            out.write(buffer, 0, read);
        }
    } finally {
        in.close();
    }
 }
}

MyApiService

public interface MyApiService {
 @Multipart
 @POST("/files")
 ApiResult uploadFile(@Part("file") TypedFile resource, @Query("path") String path);
}

SendFileTask

private class SendFileTask extends AsyncTask<String, Integer, ApiResult> {
    private ProgressListener listener;
    private String filePath;
    private FileType fileType;

    public SendFileTask(String filePath, FileType fileType) {
        this.filePath = filePath;
        this.fileType = fileType;
    }

    @Override
    protected ApiResult doInBackground(String... params) {
        File file = new File(filePath);
        totalSize = file.length();
        Logger.d("Upload FileSize[%d]", totalSize);
        listener = new ProgressListener() {
            @Override
            public void transferred(long num) {
                publishProgress((int) ((num / (float) totalSize) * 100));
            }
        };
        String _fileType = FileType.VIDEO.equals(fileType) ? "video/mp4" : (FileType.IMAGE.equals(fileType) ? "image/jpeg" : "*/*");
        return MyRestAdapter.getService().uploadFile(new CountingTypedFile(_fileType, file, listener), "/Mobile Uploads");
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        Logger.d(String.format("progress[%d]", values[0]));
        //do something with values[0], its the percentage so you can easily do
        //progressBar.setProgress(values[0]);
    }
}

Le CountingTypedFile n'est qu'une copie de TypedFile mais inclut le ProgressListener.

68
Davi Alves

Si vous souhaitez obtenir la valeur maximale afin de l'afficher sur un ProgressDialog, une notification, etc.

ProgressListener

public interface ProgressListener {
    void transferred(long num, long max);
}

CountingTypedFile

public class CountingTypedFile extends TypedFile {

    private static final int BUFFER_SIZE = 4096;

    private final ProgressListener listener;

    public CountingTypedFile(String mimeType, File file, ProgressListener listener) {
        super(mimeType, file);
        this.listener = listener;
    }

    @Override
    public void writeTo(OutputStream out) throws IOException {
        byte[] buffer = new byte[BUFFER_SIZE];
        FileInputStream in = new FileInputStream(super.file());
        long total = 0;
        try {
            int read;
            while ((read = in.read(buffer)) != -1) {
                total += read;
                this.listener.transferred(total, super.file().length());
                out.write(buffer, 0, read);
            }
        } finally {
            in.close();
        }
    }
}
0
Gnzlt