2017-08-06 88 views
0

我的Android應用程序中有以下代碼,並且不確定它是否是我的Google搜索技巧,但無法找到有關如何監視InputStream進度的良好教程。Android/Java:如何跟蹤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(); 
    } 
} 

上面的代碼工作得很好,但在場景中的內容已經從Gmail來,即使是小文件需要幾秒鐘的閱讀和填充的​​ArrayList。

是否可以顯示文件/內容讀取百分比的進度條?

回答

0

那麼,我會說跟蹤進度最簡單的方法是使用異步任務或加載程序。把你的輸入流放在一個AsyncTask中,並使用onProgressUpdate()方法跟蹤進度。

0

不適用於通用輸入流 - 您不一定知道流的內容有多大。對於特定的應用程序(例如,讀取磁盤上的文件),您可以獲取該信息。對於其他人(來自套接字的輸入流作爲示例),您將不知道總長度。對於那些你確實知道大小的人,當然你可以這麼做 - 只需在線程或AsyncTask上讀取文件即可。或者,您可以使用不確定的進度條來向用戶顯示正在進行的工作。

+0

我可以得到尺寸查詢Uri。他們只會通過本地存儲而不是通過HTTP訪問 –

0

如果我理解正確,方法是創建一個裝飾器inputstream並重寫一些方法,將chante輸入流狀態,如讀取方法或跳過method.And,然後使用觀察者模式通知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); 
     } 
    } 
} 

監聽器類是當有人改變InputStream的索引像讀取的字節或跳過字節將被調用的回調。

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

測試用例代碼:

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); 

在上面的代碼,我只是打印的讀取的字節%,而你的要求,你應該改變進程欄的位置。

這是輸出的一部分;

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=[]}