2015-11-05 4 views
13

Ich möchte, dies zu tun:Wie kann ich Ausnahmen in der Karte Griff() in einer beobachtbaren in RxJava

Observable.just(bitmap) 
      .map(new Func1<Bitmap, File>() { 
       @Override 
       public File call(Bitmap photoBitmap) { 

        //File creation throws IOException, 
        //I just want it to hit the onError() inside subscribe() 

        File photoFile = new File(App.getAppContext().getCacheDir(), "userprofilepic_temp.jpg"); 
        if(photoFile.isFile()) {//delete the file first if it exists otherwise the new file won't be created 
         photoFile.delete(); 
        } 
        photoFile.createNewFile(); //saves the file in the cache dir 

        FileOutputStream fos = new FileOutputStream(photoFile); 
        photoBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);//jpeg format 
        fos.close(); 

        return photoFile; 

       } 
      }) 
      .subscribe(//continue implementation...); 

Grundsätzlich im call() Methode, es Ausnahmen auslösen kann. Wie kann ich den Observer dazu bringen, es in onError() zu behandeln. Oder ist das nicht der richtige Weg, darüber nachzudenken?

+1

Beachten Sie, dass Operatoren wie 'map' in RxJava 2 das Werfen von geprüften Ausnahmen vom Lambda erlauben. Dies war wirklich ein Konstruktionsfehler in RxJava 1, da der genaue Fehler nicht in 'onError' von der Map Lambda propagiert werden konnte, ohne als 'RuntimeException' umgebrochen zu werden. –

Antwort

15

Rx wird immer Fehler abfangen, auch wenn dies RuntimeException ist. Sie können also eine Art Runtime-Ausnahme in catch-Block werfen. So sollte es eigentlich funktionieren.

Observable.just(bitmap) 
       .map(b -> { 
        try { 
         // do some work which throws IOException 
         throw new IOException("something went wrong"); 
        } catch (IOException e) { 
         throw new RXIOException(e); 
         // Or you can use 
         throw Exceptions.propagate(e); 
         // This helper method will wrap your exception with runtime one 
        } 
       }).subscribe(o -> { 
        // do something here 
       }, exception -> exception.printStackTrace()); 

public static class RXIOException extends RuntimeException { 
     public RXIOException(IOException throwable) { 
      super(throwable); 
     } 
} 
+0

Wenn ich versuche, dies zu tun, fragt es mich, die Ausnahme mit einem try-catch zu umgeben – Sree

+2

Sie müssen RuntimeException werfen. JVM wird dich nicht darum bitten, es mit try catch zu umgeben. Das ist die Idee –

+0

Ich habe 'call()' eine IOException werfen, aber es sagt, überschriebene Methode wirft keine IOException – Sree

4

Mit 1.0.15 gibt es die fromCallable Factory-Methode, die wir an, Sie eine Callable Instanz für jeden Teilnehmer laufen, wo Sie Ausnahmen auch geprüft werfen kann:

Observable.fromCallable(() -> {  
    File photoFile = new File(App.getAppContext().getCacheDir(), 
     "userprofilepic_temp.jpg"); 
    if (photoFile.isFile()) { 
     //delete the file if it exists otherwise the new file won't be created 
     photoFile.delete(); 
    } 
    photoFile.createNewFile(); //saves the file in the cache dir 

    FileOutputStream fos = new FileOutputStream(photoFile); 
    photoBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);//jpeg format 
    fos.close(); 

    return photoFile; 
}) 
.subscribe(...) 

Edit:

source.flatMap(v -> { 
    try { 
     //... 
     return Observable.just(result); 
    } catch (Exception e) { 
     return Observable.error(e); 
    } 
}) 
.subscribe(...); 
+0

Ich denke, das würde für diesen Fall funktionieren, aber was ist, wenn ich zwei Karten zusammenketten möchte, die auf der Ausgabe der ersten Karte beruhen. Mit 'Func1()' kann ich den Rückgabetyp und das Argument erhalten. – Sree

+0

Sie müssen flatMap, try-catch verwenden und entweder just() oder error() zurückgeben. – akarnokd

+0

kannst du mir vielleicht ein beispiel zeigen? – Sree

3

gerade erstellt Hilfsklasse diese vorformulierten an einen anderen Ort zu extrahieren:

public class RxRethrow { 
    public static <T, R> Func1<T, R> rethrow(Func1R<T, R> catchedFunc) { 
     return t -> { 
      try { 
       return catchedFunc.call(t); 
      } catch (Exception e) { 
       throw Exceptions.propagate(e); 
      } 
     }; 
    } 

    public interface Func1R<T, R> extends Function { 
     R call(T t) throws Exception; 
    } 
} 

Sie können es so nennen:

.map(RxRethrow.rethrow(products -> mapper.writer(schema).writeValueAsString(products))) 
2

Ich weiß nicht, wie die Situation war, als Diese Frage wurde zuerst gestellt und beantwortet, aber RxJava enthält momentan eine Hilfsmethode für genau diesen Zweck: Exceptions.propagate(Throwable t)

RxJava Javadoc

Convenience-Methode eine Runtime und Fehler direkt oder wickeln andere Ausnahme-Typ in eine Runtime zu werfen.

+1

yup, sein Teil der angenommenen Antwort – Sree

+0

@Sree Wow, ich habe das tatsächlich nicht bemerkt, ich wurde von der benutzerdefinierten Ausnahmeklasse geblendet. Jetzt, wo ich genauer hinsehe, kann ich sehen, dass es hier tatsächlich eine andere Antwort gibt, die dieselbe Methode verwendet. – Thorbear

Verwandte Themen