2016-11-08 50 views
2

我已经使用此代码来下载Json文件并将其转换为我的项目。 由于这里有40k项可供下载,我需要添加此文件的下载%。 我的代码是:如何插入一个百分比来下载此Json

 final Retrofit retrofit = new Retrofit.Builder() 
      .addConverterFactory(GsonConverterFactory.create()) 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
      .baseUrl(AirportService.SERVICE_ENDPOINT).build(); 


    AirportService service = retrofit.create(AirportService.class); 

    service.getAirport() 
      .subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(new Subscriber<List<Airport>>() 
      { 
       @Override 
       public void onCompleted() 
       { 

       } 

       @Override 
       public void onError(Throwable e) 
       { 
        e.printStackTrace(); 
       } 

       @Override 
       public void onNext(List<Airport> airports) 
       { 
        airps = airports; 
       } 
      }); 

,但我在改造之初,我不知道该怎么办了。 任何人都可以帮助我? 谢谢

+0

请参阅http://stackoverflow.com/a/29959083/4837089。我希望这有助于 –

+0

@SergeyNikitin我已经看到它,但我也有点困惑 – nani

回答

0

下面是我用来完成类似事情的一些代码。在我的示例中,我必须发布JSON,然后下载并解析JSON响应并将响应存储在SqLite数据库中。您需要根据您的需求调整我的代码,但这个概念很简单。解决方案基本归结为:

1)使用JsonReader自己解析Json。

2)使用FilterInputStream发布进度。

我认识到这个解决方案不使用改造,所以也许你不想使用它,但也许你会发现它有帮助。

final ProgressDialog dialog = new ProgressDialog(getActivity(), ProgressDialog.THEME_HOLO_LIGHT); 
dialog.setTitle(R.string.downloading_data); 
dialog.setMessage("Downloading data..."); 
dialog.setCanceledOnTouchOutside(false); 
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
if (!BuildConfig.DEBUG) { 
    dialog.setProgressNumberFormat(null); 
} 

mLoginTask = new AsyncTask<Void, Integer, Void>() { 
    @Override 
    protected Void doInBackground(Void... params) { 
     HttpURLConnection connection = null; 
     try { 
      byte[] request = ...; // I used a JsonWriter to write to a ByteArrayOutputStream. Since you're likely getting this from file or a GET request, this is likely not necessary. 

      URL url = new URL("https://example.com/endpoint"); 

      connection = (HttpURLConnection)url.openConnection(); 

      connection.setDoOutput(true); 
      connection.setUseCaches(false); 

      connection.setRequestMethod("POST"); 
      connection.setRequestProperty("Content-Type", "application/json; charset=utf-8"); 
      connection.setRequestProperty("Content-Length", "" + request.length); 
      connection.setRequestProperty("Accept","*/*"); 

      OutputStream out = connection.getOutputStream(); 
      out.write(request); 
      out.flush(); 
      out.close(); 

      connection.setConnectTimeout(3000); 
      connection.setReadTimeout(10000); 

      connection.connect(); 

      Thread.sleep(2000); // I don't remember why this was necessary. Likely an exception was thrown in the next line without it, at least on slower networks. 

      int responseCode = connection.getResponseCode(); 

      switch (responseCode) { 
       case 200: 
        int length = connection.getContentLength(); 

        publishProgress(0, length); 
        final InputStreamReader streamReader = new InputStreamReader(new FilterInputStream(connection.getInputStream()) { 
         private int mTotalBytesRead; 

         @Override 
         public int read() throws IOException { 
          int b = super.read(); 

          if (b > 0) { 
           updateProgress(1); 
          } 

          return b; 
         } 
         @Override 
         public int read(byte[] buffer) throws IOException { 
          return updateProgress(super.read(buffer)); 
         } 
         @Override 
         public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException { 
          return updateProgress(super.read(buffer, byteOffset, byteCount)); 
         } 
         @Override 
         public long skip(long byteCount) throws IOException { 
          return updateProgress(super.skip(byteCount)); 
         } 
         @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 int updateProgress(long numBytesRead) { 
          if (numBytesRead > 0) { 
           publishProgress(mTotalBytesRead += numBytesRead); 
          } 

          return (int)numBytesRead; 
         } 
        }); 

        JsonReader reader = new JsonReader(streamReader); 

        // your code here will depend on the format of the code. It seems like you have simply an array. 
        reader.beginArray(); 

        while (reader.peek() == JsonToken.BEGIN_OBJECT) { 
         JsonObject airport = (JsonObject) Streams.parse(reader); 
         // do some stuff with this airport. Perhaps create an Airport object and add it to an ArrayList. 
        } 
        return null; 
       default: 
        String response = IOUtils.toString(connection.getErrorStream()); 

        try { 
         Util.showToast(JsonUtil.getString(new JSONObject(response), Constants.ERROR), Toast.LENGTH_LONG); 
         if (responseCode == 403) { // Forbidden 
          publishProgress(); 
         } 
        } catch (Exception e) { 
         Util.showToast("Unsupported response\n" + connection.getHeaderField(null)+"\n"+response, Toast.LENGTH_LONG); 
        } 
        break; 
      } 
     } catch (UnknownHostException e) { 
      Util.showToast("You don't appear to be connected to the Internet.", Toast.LENGTH_LONG); 
     } catch (Exception e) { 
      if (e instanceof InterruptedIOException) { 
       return null; 
      } 
      Util.showToast(e.toString(), Toast.LENGTH_LONG); 
      Log.e("DashboardActivity", "error downloading data", e); 
     } finally { 
      if (connection != null) { 
       connection.disconnect(); 
      } 
     } 

     return null; 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
     dialog.cancel(); 
     TaskUtil.synchronize(HomeFragment.this); 
    } 

    @Override 
    protected void onCancelled() { 
     dialog.cancel(); 
     // todo: maybe you have more cleanup 
    } 

    @Override 
    protected void onProgressUpdate(Integer... values) { 
     if (values.length == 0) { 
      MyActivity.getCurrentActivity().showLoginInfo(true); 
     } else { 
      dialog.setProgress(values[0]); 
      if (values.length == 2) { 
       dialog.setMax(values[1]); 
       dialog.setIndeterminate(false); 
       dialog.show(); 
      } 
     } 
    } 
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 

dialog.setOnCancelListener(new DialogInterface.OnCancelListener() { 
    @Override 
    public void onCancel(DialogInterface dialog) { 
     mLoginTask.cancel(true); 
    } 
}); 
+0

我的问题是,我想要使用rxJava而不是一个asynctask ... – nani

+0

至少ProgressDialog部分应该是有用的然后。 –