2016-03-31 7 views
6

Wie in den Dokumenten empfohlen, habe ich einige lange Daten-Code in ein natives Modul verschoben, um den JS-Thread freizugeben, aber ich merke, dass dies immer noch die Benutzeroberfläche blockiert. Warum ist das und was kann ich tun, um das zu vermeiden?Warum blockiert dieser Aufruf eines reaktionsnativen nativen Moduls die Benutzeroberfläche?

Das native Modul wird von JS als so genannte:

MyNativeModule.fetch(path).then(data => dispatchData(data)) 

Die native Methode sieht wie folgt aus (es das Android Firebase SDK verwendet):

@ReactMethod 
public void fetch(final String path, final Promise promise) { 
    root.child(path).addListenerForSingleValueEvent(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot snapshot) { 
      if (snapshot.exists()) { 
       promise.resolve(castSnapshot(snapshot)); 
      } else { 
       promise.resolve(null); 
      } 
     } 
     @Override 
     public void onCancelled(FirebaseError firebaseError) { 
      promise.reject(firebaseError.getMessage()); 
     } 
    } 
} 

Die castSnapshot Methode wandelt die Firebase DataSnapshot Objekt in eine WriteableMap. Ich kann die Implementierung teilen, wenn das nützlich ist.

Was ich beobachtet habe, ist, dass, selbst wenn ich promise.resolve(castSnapshot(snapshot)); durch castSnapshot(snapshot); promise.resolve(null); ersetzen, blockiert der Anruf die UI: so ist es nicht die Daten über die Brücke, die der Täter ist zu senden. Wenn die Datenmenge groß ist, kann castSnapshot einige Zeit dauern, und das ist eindeutig, was blockiert.

Auch wenn dieser Code lange läuft, sollte es nicht auf ein natives Modul die UI frei bewegen? Was bekomme ich nicht darüber?

Vielen Dank.

+1

Ich habe das gleiche Problem. Ich dachte, native Module laufen auf einem anderen Thread, scheint es aber nicht. –

+2

@RomShiri yeah .. ich denke, wenn wir native Module für Perf-Gründe verwenden wollen, müssen wir Threading selbst verwalten. Aus den Dokumenten: "Native Module sollten keine Annahmen darüber haben, an welchen Thread sie aufgerufen werden [...] Wenn ein blockierender Aufruf erforderlich ist, sollte die schwere Arbeit an einen intern verwalteten Worker-Thread gesendet und alle Callbacks von verteilt werden Dort." – VonD

+0

ich fand das gleiche heraus. Ryans Ansatz war notwendig. – itinance

Antwort

3

Versuchen Sie, die root.child Linie in einer neuen Thread-Instanz, wie diese Verpackung:

@ReactMethod 
public void fetch(final String path, final Promise promise) { 
    new Thread(new Runnable() { 
     public void run() { 
      root.child(path)... 
     } 
    }).start(); 
}