【问题标题】:How to publish progress for large json file parsing with GSON如何发布使用 GSON 解析大型 json 文件的进度
【发布时间】:2015-03-09 12:41:12
【问题描述】:

亲爱的 Stackoverflowers,

我目前正在从我的原始资源中解析一个大型 json 文件。我不得不将阅读逐行更改为将 Reader 对象与 gson 结合使用,以逃避内存不足异常。到目前为止,一切顺利。

现在这一切都发生在异步任务中,我希望通过使用publishProgress() 在某种加载屏幕中通知用户进度。

InputStream raw = getResources().openRawResource(R.raw.json);
Reader rd = new BufferedReader(new InputStreamReader(raw));
Gson gson = new Gson();
mReadObjects = gson.fromJson(rd, ReadObjectList.class);

这是我目前读取文件的方式,但我不知道是否(以及如何)可以从 GSON 或 Reader 对象获取任何类型的进度更新。

非常感谢任何帮助!

【问题讨论】:

    标签: java android json android-asynctask gson


    【解决方案1】:

    您必须围绕InputStream(或Reader)编写一个包装器。

    这样的事情应该可以工作:

    public class ProgressInputStream extends FilterInputStream {
        private final int size;
        private long bytesRead;
        private int percent;
        private List<Listener> listeners = new ArrayList<>();
    
        public ProgressInputStream(InputStream in) {
            super(in);
            try {
                size = available();
                if (size == 0) throw new IOException();
            } catch (IOException e) {
                throw new RuntimeException("This reader can only be used on InputStreams with a known size", e);
            }
            bytesRead = 0;
            percent = 0;
        }
    
        public void addListener(Listener listener) {
            listeners.add(listener);
        }
    
        public void removeListener(Listener listener) {
            listeners.remove(listener);
        }
    
        @Override
        public int read() throws IOException {
            int b = super.read();
            updateProgress(1);
            return b;
        }
    
        @Override
        public int read(@NonNull byte[] b) throws IOException {
            return updateProgress(super.read(b));
        }
    
        @Override
        public int read(@NonNull byte[] b, int off, int len) throws IOException {
            return updateProgress(super.read(b, off, len));
        }
    
        @Override
        public long skip(long n) throws IOException {
            return updateProgress(super.skip(n));
        }
    
        @Override
        public void mark(int readLimit) {
            throw new UnsupportedOperationException();
        }
    
        @Override
        public void reset() throws IOException {
            throw new UnsupportedOperationException();
        }
    
        @Override
        public boolean markSupported() {
            return false;
        }
    
        private <T extends Number> T updateProgress(T numBytesRead) {
            if (numBytesRead.longValue() > 0) {
                bytesRead += numBytesRead.longValue();
                if (bytesRead * 100 / size > percent) {
                    percent = (int) (bytesRead * 100 / size);
                    for (Listener listener : listeners) {
                        listener.onProgressChanged(percent);
                    }
                }
            }
            return numBytesRead;
        }
    
        public interface Listener {
            void onProgressChanged(int percentage);
        }
    }
    

    使用方法:

    ProgressInputStream raw = new ProgressInputStream(getResources().openRawResource(R.raw.json));
    raw.addListener(new ProgressInputStream.Listener() {
        @Override
        public void onProgressChanged(int percentage) {
            publishProgress(percentage);
        }
    });
    Reader rd = new BufferedReader(new InputStreamReader(raw));
    

    【讨论】:

    • 我不知道为什么这只有一票并且没有被标记为正确。这对我帮助很大,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2015-07-10
    • 1970-01-01
    • 2013-04-28
    • 2012-04-21
    • 1970-01-01
    • 2017-06-10
    相关资源
    最近更新 更多