简体   繁体   English

Android / Java:如何跟踪InputStream的进度

[英]Android/Java: How to track progress of InputStream

I have the following code in my Android app, and not sure whether it is my Googling skills, but am not able to find a good tutorial on how to monitor progress of InputStream. 我的Android应用程序中包含以下代码,不确定是否是我的谷歌搜索技能,但无法找到有关如何监视InputStream进度的良好教程。

private void restoreFromUri(Uri uri) {
    try {
        InputStream is = getContentResolver().openInputStream(uri);
        ObjectInputStream ois = new ObjectInputStream(is);
        ArrayList<String> myList = (ArrayList) ois.readObject();
        ois.close();
        is.close();
    } catch (Exception e) {
        Snackbar.make(snackView, e.getMessage(), Snackbar.LENGTH_LONG).show();
    }
}

The above code works well, but in scenarios where the content is coming from GMail, even a small file takes a few seconds to read and populate the ArrayList. 上面的代码很好用,但是在内容来自GMail的情况下,即使是一个小文件也要花费几秒钟来读取和填充ArrayList。

Is it possible to show a progress bar with the percentage of file/content read? 是否可以显示进度条以及读取的文件/内容的百分比?

If i understand correctly,the approach is create a decorator inputstream and override some method which will chante the inputstream state like read method or skip method.And then use observer pattern notify the moinotr the percent of read.See the following code: 如果我没有正确理解,该方法是创建一个装饰器输入流并重写某些方法来改变输入流的状态,如read方法或skip方法。然后使用观察者模式通知Moinotr读取的百分比。请参见以下代码:

    public static class ProcessInputStream extends InputStream{

    private InputStream in;
    private int length,sumRead;
    private java.util.List<Listener> listeners;
    private double percent;

    public ProcessInputStream(InputStream inputStream,int length) throws IOException{
        this.in=inputStream;
        listeners=new ArrayList<>();
        sumRead=0;
        this.length=length;
    }


    @Override
    public int read(byte[] b) throws IOException {
        int readCount = in.read(b);
        evaluatePercent(readCount);
        return readCount;
    }



    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        int readCount = in.read(b, off, len);
        evaluatePercent(readCount);
        return readCount;
    }

    @Override
    public long skip(long n) throws IOException {
        long skip = in.skip(n);
        evaluatePercent(skip);
        return skip;
    }

    @Override
    public int read() throws IOException {
        int read = in.read();
        if(read!=-1){
            evaluatePercent(1);
        }
        return read;
    }

    public ProcessInputStream addListener(Listener listener){
        this.listeners.add(listener);
        return this;
    }

    private void evaluatePercent(long readCount){
        if(readCount!=-1){
            sumRead+=readCount;
            percent=sumRead*1.0/length;
        }
        notifyListener();
    }

    private void notifyListener(){
        for (Listener listener : listeners) {
            listener.process(percent);
        }
    }
}

The Listener class is a callback which will be invoked when someone change the index of inputstream like read bytes or skip bytes. Listener类是一个回调,当有人更改输入流的索引(如读取字节或跳过字节)时将调用该回调。

public interface Listener{
    void process(double percent);
}

The test case code: 测试用例代码:

    UserInfo userInfo=new UserInfo();
    userInfo.setName("zyr");
    userInfo.setPassword("123");
    userInfo.setTestString(new ArrayList<>());
    System.out.println(userInfo);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos=new ObjectOutputStream(bos);
    oos.writeObject(userInfo);
    byte[] objectBytes = bos.toByteArray();
    oos.close();
    bos.close();


    ProcessInputStream processInputStream = new ProcessInputStream(new ByteArrayInputStream(objectBytes),objectBytes.length);


    processInputStream.addListener(percent -> System.out.println(percent));
    ObjectInputStream ois=new ObjectInputStream(processInputStream);


    UserInfo target = (UserInfo) ois.readObject();
    System.out.println(target);

In the above code,i just print the percent of read bytes,with your requirement,you should change the position of the process bar. 在上面的代码中,我只打印读取字节的百分比,根据您的要求,您应该更改进程栏的位置。

And this is a part of output; 这是输出的一部分;

UserInfo{id=0, name='zyr', password='123', testString=[]}
0.008658008658008658
0.017316017316017316
0.021645021645021644
......
......
0.9523809523809523
0.9696969696969697
0.974025974025974
0.9783549783549783
0.9956709956709957
1.0
UserInfo{id=0, name='zyr', password='123', testString=[]}

Well, I would say the simplest way to track progress would be to use an Async Task or a Loader. 好吧,我想说,跟踪进度的最简单方法是使用异步任务或加载程序。 Put your input stream in an AsyncTask and track the progress by using its onProgressUpdate() method. 将输入流放在AsyncTask中,并使用其onProgressUpdate()方法跟踪进度。

Not for a generic input stream- you don't necessarily know how big the contents of a stream are. 不是通用输入流-您不一定知道流的内容有多大。 For specific applications (reading a file on disk, for example) you can get that information. 对于特定的应用程序(例如,读取磁盘上的文件),您可以获得该信息。 For others (the input stream from a socket as an example) you won't know the total length. 对于其他对象(例如来自套接字的输入流),您将不知道总长度。 For those you do know the size of, of course you can do that- just read the file on a thread or AsyncTask. 对于那些您确实知道大小的人,您当然可以做到这一点-只需在线程或AsyncTask上读取文件即可。 Or you could use an indeterminate rogress bar just to show the user that work is happening. 或者,您可以使用不确定的进度条只是向用户显示工作正在进行中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM