Jak postavit reakčně nativní most a získat prohlížeč PDF

React Native umožňuje vytvářet nativní aplikace pomocí jazyka JavaScript a má k dispozici velké množství součástí a funkcí. Některé součásti nebo funkce však ve výchozím nastavení nejsou k dispozici. A někdy je nutné zlepšit výkon některých součástí. V těchto případech lze použít nativní implementaci.

Tento článek popisuje, jak vytvořit most mezi JavaScriptem a nativní implementací, a uvádí příklad, jak vytvořit PDF Viewer pro React Native pro vykreslování dokumentů PDF.

Všechny zdroje jsou k dispozici v gitlab nebo jako NPM balíček:

  • Balíček NPM reag-native-view-pdf (https://www.npmjs.com/package/react-native-view-pdf)
  • Zdroje Gitlab rumax / reag-native-PDFView (https://github.com/rumax/react-native-PDFView)

Začínáme

Nejprve připravte projekt. Otevřete terminál a spusťte:

$ create-reagovat-nativní-aplikace reagovat-nativní-PDFView
$ cd Reakce-nativní-PDFView
$ vysunutí příze

Zkontrolujte, zda projekt funguje:

$ příze spustit android

a otevřete ji v IDE. Dávám přednost Atomu, proto v terminálu mohu udělat:

$ atom.

Chcete-li pracovat se zdroji Java, otevřete Android Studio.

Implementace Java

V Android Studio:

  • vytvořte novou knihovnu reakčních knihoven
  • vytvářet nové třídy Java PDFView, PDFViewManager a PDFViewPackage

PDFViewPackage

Podle oficiální dokumentace by PDFViewPackage měl implementovat ReactPackage a chybějící metody createNativeModules a createViewManagers by měly být přidány:

veřejná třída PDFViewPackage implementuje ReactPackage {
    @Override
    veřejný seznam  createNativeModules (ReactApplicationContext reaContext) {
        return Collections.emptyList ();
    }
    veřejný seznam  createViewManagers (ReactApplicationContext reaContext) {
        return Arrays.  asList (nový PDFViewManager (eaktutext));
    }
}

Android Studio upozorní na chybu PDFViewManager nelze použít na ..., která musí být opravena implementací PDFViewManager.

PDFViewManager

PDFViewManager by měl rozšířit SimpleViewManager a implementovat chybějící metody:

  • getName který - by měl vrátit název třídy reakcí
  • createViewInstance je místo, kde by měl být prohlížeč inicializován

Kód je:

veřejná třída PDFViewManager rozšiřuje SimpleViewManager  {
    private static final String REACT_CLASS = "PDFView";
    soukromý PDFView pdfView = null;
    soukromý kontextový kontext;
    veřejný PDFViewManager (ReactApplicationContext context) {
        this.context = context;
    }
    @Override
    public String getName () {
        návrat REACT_CLASS;
    }
    @Override
    veřejný PDFView createViewInstance (kontext ThemedReactContext) {
        if (pdfView == null) {
            pdfView = nový PDFView (kontext);
        }
        návrat pdfView;
    }
}

s chybou, že by PDFView měl rozšířit pohled, který musí být opraven implementací PDFView.

PDFView

PDFView by měl rozšiřovat android.view.View a implementace je docela jednoduchá:

veřejná třída PDFView rozšiřuje android.view.View {
    soukromý kontext ThemedReactContext;
    veřejný PDFView (kontext ThemedReactContext) {
        super (kontext);
        this.context = context;
    }
}

V tuto chvíli jsou všechny třídy připraveny a PDFViewPackage lze zaregistrovat.

Zaregistrujte PDFViewPackage

V MainApplication.java je metoda getPackages. Přímo pod MainReactPackage lze zaregistrovat balíček PDFViewPackage:

@Override
chráněný seznam  getPackages () {
  return Arrays.  asList (
      nový MainReactPackage (),
      nový PDFViewPackage ()
  );
}

Počáteční implementace Java je připravena!

Implementace JavaScriptu

V Atomu vytvořte novou složku PDFView a vytvořte dva soubory:

  • index.js
  • RNPDFView.js

PDFView / RNPDFView.js

Toto je hlavní soubor, kde by měla být vyžadována nativní komponenta PDFView Reaction a musí být definováno rozhraní komponenty:

importovat {requNativeComponent, ViewPropTypes} z 'reaktivního';
importovat PropTypes z 'prop-typů';
const componentInterface = {
  název: 'PDFView',
  propTypes: {
    ... ViewPropTypes,
  },
};
exportovat výchozí požadavekNativeComponent ('PDFView', componentInterface);

V tuto chvíli jsou používány pouze ViewPropTypes ke kontrole, zda je komponenta správně definována a může být použita. Všechny ostatní vlastnosti budou přidány později.

PDFView / index.js

Tento soubor je volitelný a lze jej použít jako komponentu wrapper, ke zpracování chyb / stavů načítání nebo k použití typů toků atd.:

/ * @ flow * /
import Reagovat z 'reagovat';
importovat RNPDFView z './RNPDFView';
typ Props = {};
třída PDFView rozšiřuje React.Component  {
  static defaultProps = {};
  konstruktor (rekvizity: Props) {
    super (rekvizity);
  }
  poskytnout() {
    návrat ;
  }
}
exportovat výchozí PDFView;

App.js

Most je připraven a lze jej importovat a použít:

importovat PDFView z './PDFView/index';
...
vrátit se (
  
    
  
);

Protože implementuje android.view.View v Javě, měl by se také chovat jako komponenta View-native. To lze zkontrolovat definováním stylů:

const styles = StyleSheet.create ({
  pdfView: {
    výška: 400,
    šířka: 300,
    backgroundColor: 'green',
  },
  ...

Restartujte aplikaci a dostanete zelený obdélník, jako je tento:

Styling komponenty

Ve skutečnosti je to všechno pro most, kromě vlastností a zpětných volání. A pokud nejsou vyžadovány, je již možné implementovat komponentu do Java.

Implementace prohlížeče PDF

Chcete-li implementovat PDF Viewer, je třeba vědět:

  • resource - Řetězcová hodnota pro definování zdroje, který se má vykreslit. Mohou to být data URL, filePath nebo base64
  • resourceType - Řetězcová hodnota pro definování typu zdroje

A samozřejmě získat zpětnou vazbu z nativní části do JavaScriptu:

  • onError - Funkce zpětného volání, která musí být vyvolána, je vyvolána omylem
  • onLoad - Funkce zpětného volání, která musí být vyvolána po dokončení načítání

Předat vlastnosti z JavaScriptu

V PDFView / RNPDFView.js rozšiřte komponenty componentInterface.propTypes o vlastnosti popsané výše:

const componentInterface = {
  název: 'PDFView',
  propTypes: {
    onError: PropTypes.func,
    onLoad: PropTypes.func,
    zdroj: PropTypes.string,
    resourceType: PropTypes.string,
    ... ViewPropTypes,
  },
};

Udělejte to samé v PDFView / index.js, ale použijte typy toků:

napište Props = {
  onError: (Error) => void,
  onLoad: () => neplatné,
  zdroj: string,
  resourceType: 'url' | 'base64' | 'soubor',
};

A definujte metodu onError pro předávání pouze nativeEvent ze komponenty:

onError: (chyba: Chyba) => neplatné; // Definice typu toku
onError (event: any) {
  this.props.onError (event && event.nativeEvent || nová chyba ());
}

Nezapomeňte to v konstruktoru svázat:

konstruktor (rekvizity: Props) {
  super (rekvizity);
  this.onError = this.onError.bind (this);
}

A opravit metodu renderování:

poskytnout() {
  const {onError, ... zbývajícíProps} = this.props;
  návrat ;
}

Pro zjednodušení použití komponenty lze také definovat výchozí vlastnosti:

static defaultProps = {
  onError: () => {},
  onLoad: () => {},
  resourceType: 'url',
};

Implementace JavaScriptu je nyní dokončena.

Získejte a používejte vlastnosti v Javě

Přepněte do aplikace Android Studio a otevřete třídu PDFViewManager. Na tomto místě jsou přístupné všechny vlastnosti definované v JavaScriptu. Definujte zdroj:

@ReactProp (name = "resource")
public void setResource (PDFView pdfView, String resource) {
    pdfView.setResource (zdroj);
}

A totéž platí pro resourceType (zpětná volání budou implementována později):

@ReactProp (name = "resourceType")
public void setResourceType (PDFView pdfView, String resourceType) {
    pdfView.setResourceType (resourceType);
}

Implementace ve třídě PDFView bude:

private String resourceType;
soukromý zdroj String;
    
public void setResource (String resource) {
    this.resource = resource;
}
public void setResourceType (String resourceType) {
    this.resourceType = resourceType;
}

V PDFViewManageru vyhledejte následující metody:

  • onAfterUpdateTransaction je to místo, kde by se komponenta měla vykreslit po nastavení všech vlastností:
@Override
veřejné neplatné naAfterUpdateTransaction (PDFView pdfView) {
    super.onAfterUpdateTransaction (pdfView);
    pdfView.render ();
}
  • onDropViewInstance je to další metoda, která se nazývá, když je komponenta React Native odpojena. Implementace může být následující:
@Override
public void onDropViewInstance (PDFView pdfView) {
    super.onDropViewInstance (pdfView);
    pdfView.onDrop ();
}

Používejte zpětná volání JavaScriptu v Javě

Chcete-li použít načtení kompletní, chybová zpětná volání je nutné předat tyto události. Otevřete soubor PDFView.java a definujte metody loadComplete a onError:

@Override
public void loadComplete (int numberOfPages) {
    responseNativeEvent ("onLoad", null);
}
@Override
public void onError (Exception ex) {
    eaktativeEvent ("onError", "error:" + t.getMessage ());
}

a implementovat metodu reagNativeEvent. Podle oficiální dokumentace by to mělo být:

private void reakNativeEvent (String eventName, String message) {
    Eventable WritableMap = Arguments.createMap ();
    event.putString ("message", message);
    ReactContext reaContext = (ReactContext) this.getContext ();
    Reagovat
            .getJSModule (RCTEventEmitter.class)
            .receiveEvent (this.getId (), eventName, event);
}

A v PDFViewManageru

veřejná mapa getExportedCustomBubblingEventTypeConstants () {
    návrat MapBuilder
            .stavitel()
            .dát(
                    "onLoad",
                    MapBuilder.of ("phasedRegistrationNames", MapBuilder.of ("bubbled", "onLoad"))
            )
            .dát(
                    "onError",
                    MapBuilder.of ("phasedRegistrationNames", MapBuilder.of ("bubbled", "onError"))
            )
            .stavět();
}

Realizace mostu je připravena! Zbývá pouze implementovat soubor PDFViewer.java. Použil jsem implementaci AndroidPdfViewer a konečné řešení, které najdete v gitlab (https://github.com/rumax/react-native-PDFView).

Výsledek

Implementace mostu a prohlížeče PDF je připravena. Definujte dokument, který chcete vykreslit:


   console.log ('onError', error)}
    onLoad = {() => console.log ('onLoad')}
    resource = "http://www.pdf995.com/samples/pdf.pdf" />

..znovu načíst aplikaci a namísto zeleného obdélníku získáte dokument PDF:

Výsledky prohlížeče PDF