2017-08-16 6 views
0

Ich versuche, meine Asynch-Aufgabe zu JavaRx 2 zu konvertieren. Ich verwende Google Sheets API, um Daten aus Tabellen herunterzuladen. (here is a link how this happens)RxJava 2 - Schwerwiegende Ausnahme auf Scheduler geworfen

Hier ist ein Teil meiner Code:

OnCreate:

/** 
* JavaRx 
*/ 

//Observable 
Observable<String> observable 
     = Observable.create(
     new ObservableOnSubscribe<String>() { 
      @Override 

      public void subscribe(ObservableEmitter<String> e) throws Exception { 
       //Use onNext to emit each item in the stream// 
       e.onNext("https://docs.google.com/spreadsheets/d/1W5S5W2QH6WHjUcL1VMwqIqOdFYVleTopJNryQJGw568/gviz/tq?tqx=out:QUERY&tq=select+B,X,Y,Z"); 

        //Once the Observable has emitted all items in the sequence, call onComplete// 
       e.onComplete(); 
      } 
     } 
    ).subscribeOn(Schedulers.io()) 
      .observeOn(AndroidSchedulers.mainThread()); 

//Create our subscription 
Observer<String> observer = new Observer<String>() { 
    @Override 
    public void onSubscribe(Disposable d) { 
     Log.e(TAG, "onSubscribe " + Thread.currentThread().getName()); 
    } 

    @Override 
    public void onNext(String value) { 
     try { 
      String data = getLeagueData(value); 
      mLeagues.add(autoProcessJsonLeague("Argentina Primera Division", returnJSON(data))); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     Log.e(TAG, "onNext: " + value + Thread.currentThread().getName()); 

    } 

    @Override 
    public void onError(Throwable e) { 
     Log.e(TAG, "onError: "); 
    } 

    @Override 
    public void onComplete() { 
     Log.e(TAG, "onComplete: All Done! " + Thread.currentThread().getName()); 
    } 
}; 
observable.subscribe(observer); 

Andere Methoden:

private String getLeagueData(String urlString) throws IOException { 
//Download JSON file 
    InputStream is = null; 

    try { 
     URL url = new URL(urlString); 
     HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); 
     conn.setInstanceFollowRedirects(true); //you still need to handle redirect manually. 
     HttpsURLConnection.setFollowRedirects(true); 
     conn.setReadTimeout(10000 /* milliseconds */); 
     conn.setConnectTimeout(15000 /* milliseconds */); 
     conn.setInstanceFollowRedirects(true); 
     conn.setRequestMethod("GET"); 
     conn.setDoInput(true); 
     // Starts the query 
     conn.connect(); //ERROR HAPPENS HERE! 
     int responseCode = conn.getResponseCode(); 
     is = conn.getInputStream(); 

     String contentAsString = convertStreamToString(is); 
     //Log.d("contentAsString", contentAsString); 
     return contentAsString; 
    } catch (ProtocolException e) { 
     e.printStackTrace(); 
    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     if (is != null) { 
      is.close(); 
     } 
    } 

    return null; 
} 

private String convertStreamToString(InputStream is) { 
    BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 
    StringBuilder sb = new StringBuilder(); 

    String line = null; 
    try { 
     while ((line = reader.readLine()) != null) { 
      sb.append(line + "\n"); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      is.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
    return sb.toString(); 
} 


private League autoProcessJsonLeague(String leagueName, JSONObject object) { 
    //Get the data from the JSON string 
    ArrayList<Team> teams = new ArrayList<>(); 
    try { 
     JSONArray rows = object.getJSONArray("rows"); 
     for (int r = 0; r < rows.length(); ++r) { 
      JSONObject row = rows.getJSONObject(r); 
      JSONArray columns = row.getJSONArray("c"); 
      String name = columns.getJSONObject(0).getString("v"); 
      int points = columns.getJSONObject(1).getInt("v"); 
      double hGoalAv = columns.getJSONObject(2).getDouble("v"); 
      double aGoalAv = columns.getJSONObject(3).getDouble("v"); 
      hGoalAv = Utilities.round(hGoalAv, 2); 
      aGoalAv = Utilities.round(aGoalAv, 2); 
      teams.add(new Team(name, points, hGoalAv, aGoalAv)); 
      //Log.d("Team", name + " " + hGoalAv + " " + aGoalAv); 
     } 
    } catch (JSONException e) { 
     e.printStackTrace(); 
     e.printStackTrace(); 
    } 
    return new League(leagueName, teams); 
} 

So erstelle ich einen beobachtbaren, ich auf IO-Thread und observeOn abonnieren der Haupt-Bedroung. Mit onNext sende ich den URL-Link an den Beobachter und dann versuche ich mich mit dem Server zu verbinden, um die JSON-String-Datei herunterzuladen.

Fehler passiert bei der Methode getLeagueData() in der Zeile conn.connect(); Es sagt java.lang.IllegalStateException: Schwerwiegende Ausnahme auf Scheduler geworfen.

FULL STACK TRACE ERROR:

08-16 08:53:09.934 29841-29841/com.aresproductions.bettingtools E/AndroidRuntime: FATAL EXCEPTION: main 
Process: com.aresproductions.bettingtools, PID: 29841 
java.lang.IllegalStateException: Fatal Exception thrown on Scheduler. 
    at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:111) 
    at android.os.Handler.handleCallback(Handler.java:751) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:154) 
    at android.app.ActivityThread.main(ActivityThread.java:6195) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:874) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:764) 
Caused by: android.os.NetworkOnMainThreadException 
    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303) 
    at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:86) 
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:74) 
    at java.net.InetAddress.getAllByName(InetAddress.java:752) 
    at com.android.okhttp.internal.Network$1.resolveInetAddresses(Network.java:29) 
    at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:187) 
    at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:156) 
    at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:98) 
    at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:346) 
    at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:329) 
    at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:247) 
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:457) 
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:126) 
    at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89) 
    at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java) 
    at com.aresproductions.bettingtools.MainActivity.getLeagueData(MainActivity.java:307) 
    at com.aresproductions.bettingtools.MainActivity.access$000(MainActivity.java:80) 
    at com.aresproductions.bettingtools.MainActivity$2.onNext(MainActivity.java:180) 
    at com.aresproductions.bettingtools.MainActivity$2.onNext(MainActivity.java:171) 
    at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:198) 
    at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:250) 
    at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:109) 
    at android.os.Handler.handleCallback(Handler.java:751)  
    at android.os.Handler.dispatchMessage(Handler.java:95)  
    at android.os.Looper.loop(Looper.java:154)  
    at android.app.ActivityThread.main(ActivityThread.java:6195)  
    at java.lang.reflect.Method.invoke(Native Method)  
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:874)  
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:764)  
08-16 08:53:09.936 29841-29841/com.aresproductions.bettingtools E/MQSEventManagerDelegate: failed to get MQSService. 

Vielen Dank im Voraus!

+1

Sie setzen wahrscheinlich etwas auf HttpURLConnection, nachdem die Verbindung geöffnet wurde. Sind Sie sicher, wo die Ausnahme passiert? Haben Sie eine vollständige Stapelverfolgung der Ausnahme? –

Antwort

2

Das Problem besteht darin, dass Sie den Netzwerkaufruf auf dem Hauptthread ausführen. Obwohl Sie sich unter Schedulers.io() angemeldet haben, wird die Methode onNext(), bei der Sie den Netzwerkanruf tätigen, am Hauptthread aufgerufen, da Sie den Hauptthread observeOn(AndroidSchedulers.mainThread()) beobachten.

Die Lösung wird sein, die getLeagueData(String urlString) innerhalb subscribe() Methode der beobachtbaren aufrufen und e.onNext(result) mit dem Ergebnis des Netzwerkaufrufs aufrufen.

2

Ich nehme an, Sie erhalten ein Netzwerk auf Haupt Thread Ausnahme, weil der Netzwerkanruf an der falschen Stelle ist. Sie sollten es in die bewegte schaffen so wird es auf dem IO-Scheduler statt als Teil der Beobachtung der trivialen Zeichenfolge ausgeführt:

Observable<String> observable = Observable.create(
    new ObservableOnSubscribe<String>() { 
     @Override 
     public void subscribe(ObservableEmitter<String> e) throws Exception { 

      String value = "https://docs.google.com/spreadsheets/d/1W5S5W2QH6WHjUcL1VM" + 
       "wqIqOdFYVleTopJNryQJGw568/gviz/tq?tqx=out:QUERY&tq=select+B,X,Y,Z"; 

      String data = getLeagueData(value); 

      //Use onNext to emit the item in the stream// 
      e.onNext(data); 

      /* Once the Observable has emitted all items 
      in the sequence, call onComplete */ 
      e.onComplete(); 
     } 
    } 
) 
.subscribeOn(Schedulers.io()) 
.observeOn(AndroidSchedulers.mainThread()); 

//Create our subscription 
Observer<String> observer = new Observer<String>() { 
    @Override 
    public void onSubscribe(Disposable d) { 
     Log.e(TAG, "onSubscribe " + Thread.currentThread().getName()); 
    } 

    @Override 
    public void onNext(String data) { 
     try { 
      mLeagues.add(autoProcessJsonLeague(
       "Argentina Primera Division", returnJSON(data))); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 


     Log.e(TAG, "onNext: " + value + Thread.currentThread().getName()); 

    } 

    @Override 
    public void onError(Throwable e) { 
     Log.e(TAG, "onError: "); 
    } 

    @Override 
    public void onComplete() { 
     Log.e(TAG, "onComplete: All Done! " + Thread.currentThread().getName()); 
    } 
}; 
observable.subscribe(observer); 

Sie auch

autoProcessJsonLeague(
       "Argentina Primera Division", returnJSON(data)) 

in die ObservableOnSubscribe im Fall bewegen möchten die Verarbeitung ist teuer.

+0

Vielen Dank, Ihre Lösung ist auch sehr klar und umfassend. Entschieden, die Antwort von Arjun zu akzeptieren, weil er einen niedrigeren Ruf hat. Leider kann ich beides nicht wählen. – AresProductions

Verwandte Themen