Как да се изгради мост на реагиране и да получите PDF Viewer

React Native позволява да се изграждат родните приложения, използвайки езика на JavaScript и има огромно количество компоненти и функционалност. Но някои компоненти или функции не са достъпни по подразбиране. И понякога е необходимо да се подобри работата на някои компоненти. В тези случаи може да се използва нативното им изпълнение.

Тази статия описва как да се направи мост между JavaScript и собствена реализация и дава пример как да се изгради PDF Viewer за React Native за изобразяване на PDF документи.

Всички източници са достъпни в gitlab или като NPM пакет:

  • NPM пакет react-native-view-pdf (https://www.npmjs.com/package/react-native-view-pdf)
  • Източници на Gitlab rumax / react-native-PDFView (https://github.com/rumax/react-native-PDFView)

Приготвяме се да започнем

Първо подгответе проект. Отворете терминал и стартирайте:

$ create-react-native-app react-native-PDFView
$ cd react-native-PDFView
$ изваждане на прежда

Проверете дали проектът работи:

$ прежда за Android

и го отворете в IDE. Предпочитам Atom, затова в терминал мога да направя:

$ атом.

Отворете Android Studio, за да работите с източници на Java.

Реализация на Java

В Android Studio:

  • създаване на нов библиотека за реакции
  • създайте нови Java класове PDFView, PDFViewManager и PDFViewPackage

PDFViewPackage

Според официалната документация PDFViewPackage трябва да реализира ReactPackage и липсващите createNativeModules и методите createViewManagers трябва да се добавят:

публичен клас PDFViewPackage реализира ReactPackage {
    @Override
    обществен списък  createNativeModules (ReactApplicationContext reactContext) {
        върнете Collections.emptyList ();
    }
    обществен списък  createViewManagers (ReactApplicationContext reactContext) {
        връщам масиви.  asList (нов PDFViewManager (reactContext));
    }
}

Android Studio ще подчертае грешка, която PDFViewManager не може да бъде приложена към ..., която трябва да бъде коригирана чрез прилагане на PDFViewManager.

PDFViewManager

PDFViewManager трябва да разшири SimpleViewManager и внедрява липсващи методи:

  • getName който - трябва да връща името на реагиращия клас
  • createViewInstance е място, където зрителят трябва да се инициализира

Кодът е:

PDFViewManager за обществен клас разширява SimpleViewManager  {
    частен статичен окончателен String REACT_CLASS = "PDFView";
    частен PDFView pdfView = null;
    частен контекст;
    публичен PDFViewManager (контекст на ReactApplicationContext) {
        this.context = контекст;
    }
    @Override
    public String getName () {
        връщане REACT_CLASS;
    }
    @Override
    публичен PDFView createViewInstance (контекст на ThemedReactContext) {
        ако (pdfView == null) {
            pdfView = нов PDFView (контекст);
        }
        връщане pdfView;
    }
}

с грешката, че PDFView трябва да разшири View, което трябва да бъде поправено чрез внедряване на PDFView.

PDFView

PDFView трябва да разширява android.view.View и реализацията е доста проста:

PDFView в обществен клас разширява android.view.View {
    частен контекст ThemedReactContext;
    публичен PDFView (контекст на ThemedReactContext) {
        супер (контекст);
        this.context = контекст;
    }
}

В този момент всички класове са готови и PDFViewPackagecan може да бъде регистриран.

Регистрирайте PDFViewPackage

В MainApplication.java е методът getPackages. Точно под MainReactPackage пакетът PDFViewPackage може да бъде регистриран:

@Override
защитен списък  getPackages () {
  връщане масиви.  asList (
      нов MainReactPackage (),
      нов PDFViewPackage ()
  );
}

Първоначалната реализация на Java е готова!

Изпълнение на JavaScript

В Atom създайте нова папка PDFView и създайте два файла:

  • index.js
  • RNPDFView.js

PDFView / RNPDFView.js

Това е основният файл, в който трябва да се изисква нативният компонент на реакцията на PDFView и трябва да се дефинира интерфейс на компонента:

import {requNativeComponent, ViewPropTypes} от „react-native“;
импортиране на PropTypes от 'prop-type';
const компонентинтерфейс = {
  име: „PDFView“,
  propTypes: {
    ... ViewPropTypes,
  }
};
експортиране по подразбиране изискватNativeComponent ('PDFView', компонентинтерфейс);

В този момент се използват само ViewPropTypes, за да се провери дали компонентът е дефиниран правилно и може да се използва. Всички останали свойства ще бъдат добавени по-късно.

PDFView / index.js

Този файл е незадължителен и може да се използва като обвиващ компонент, за обработка на грешки / състояния на зареждане или за използване на типове потоци и т.н.:

/ * @flow * /
import React от 'реагира';
импортиране на RNPDFView от './RNPDFView';
въведете подпори = {};
клас PDFView разширява React.Component  {
  статични defaultProps = {};
  конструктор (подпори: подпори) {
    супер (подпори);
  }
  render () {
    връщане ;
  }
}
експортиране по подразбиране PDFView;

App.js

Мостът е готов и може да бъде внесен и използван:

импортиране на PDFView от './PDFView/index';
...
връщане (
  <Преглед на стил = {styles.container}>
    
  
);

Тъй като внедрява android.view.View в Java, той също трябва да се държи като нативен компонент на View react. Това може да се провери чрез определяне на стилове:

const styles = StyleSheet.create ({
  pdfВижте: {
    височина: 400,
    ширина: 300,
    backgroundColor: 'зелен',
  }
  ...

Рестартирайте приложението и ще получите зелен правоъгълник като този:

Стилизиране на компонента

Всъщност това е всичко за моста, с изключение на свойствата и обратните повиквания. И ако те не са необходими, вече е възможно компонентът да се реализира в Java.

Реализация на PDF Viewer

За да внедрите PDF Viewer е необходимо да знаете:

  • resource - String value за определяне на ресурса за изобразяване. Могат да бъдат URL, dataPath или base64 данни
  • resourceType - String стойност за определяне на типа ресурс

И разбира се, получете малко отзиви от родната част към JavaScript:

  • onError - Функцията за обратно извикване, която трябва да бъде, се извиква при грешка
  • onLoad - Функцията за обратно извикване, която трябва да бъде извикана, при зареждане приключи

Предавайте свойства от JavaScript

В PDFView / RNPDFView.js разширете компонентаInterface.propTypes със свойствата, описани по-горе:

const компонентинтерфейс = {
  име: „PDFView“,
  propTypes: {
    onError: PropTypes.func,
    onLoad: PropTypes.func,
    ресурс: PropTypes.string,
    resourceType: PropTypes.string,
    ... ViewPropTypes,
  }
};

Направете същото в PDFView / index.js, но използвайки типове потоци:

тип Подпори = {
  onError: (Грешка) => void,
  onLoad: () => void,
  ресурс: string,
  resourceType: 'url' | 'base64' | "Файл",
};

И дефинирайте метод onError за преминаване само nativeEvent от компонента:

onError: (грешка: Грешка) => void; // Определение на типа на потока
onError (събитие: всяко) {
  this.props.onError (събитие && event.nativeEvent || нова грешка ());
}

Не забравяйте да свържете това в конструктор:

конструктор (подпори: подпори) {
  супер (подпори);
  this.onError = this.onError.bind (това);
}

И коригирайте метода на изобразяване:

render () {
  const {onError, ... preostaProps} = this.props;
  връщане ;
}

Също така свойствата по подразбиране могат да бъдат определени за опростяване на използването на компонента:

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

Реализацията на JavaScript е завършена сега.

Вземете и използвайте свойства в Java

Превключете към Android Studio и отворете PDFViewManager клас. Това е мястото, където могат да бъдат достъпни всички свойства, дефинирани в JavaScript. Определете ресурса:

@ReactProp (name = "ресурс")
public void setResource (PDFView pdfView, String resource) {
    pdfView.setResource (ресурс);
}

И същото за resourceType (Callbacks ще бъдат внедрени по-късно):

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

Внедряването в клас PDFView ще бъде:

private String resourceType;
частен String ресурс;
    
public void setResource (String resource) {
    this.resource = ресурс;
}
public void setResourceType (String resourceType) {
    this.resourceType = resourceType;
}

В PDFViewManager намерете следните методи:

  • onAfterUpdateTransaction това е мястото, където компонентът трябва да бъде представен, след като са зададени всички свойства:
@Override
обществена невалидност onAfterUpdateTransaction (PDFView pdfView) {
    super.onAfterUpdateTransaction (pdfView);
    pdfView.render ();
}
  • onDropViewInstance това е друг метод, който се извиква, когато компонентът React Native е демонтиран. Изпълнението може да бъде следното:
@Override
публична невалидност onDropViewInstance (PDFView pdfView) {
    super.onDropViewInstance (pdfView);
    pdfView.onDrop ();
}

Използвайте обратно извикване на JavaScript в Java

За да използвате зареждането пълно, грешките при извикване на грешки е необходимо да се предадат тези събития. Отворете PDFView.java и дефинирайте loadComplete и onError методи:

@Override
public void loadComplete (int numberOfPages) {
    reactNativeEvent ("onLoad", null);
}
@Override
публично void onError (Изключение ex) {
    reactNativeEvent ("onError", "error:" + t.getMessage ());
}

и прилагаме метода reactNativeEvent. Според официалната документация трябва да бъде:

private void reactNativeEvent (String eventName, String message) {
    WritableMap събитие = Arguments.createMap ();
    event.putString ("съобщение", съобщение);
    ReactContext reactContext = (ReactContext) this.getContext ();
    reactContext
            .getJSModule (RCTEventEmitter.class)
            .receiveEvent (this.getId (), eventName, събитие);
}

И в PDFViewManager

обществена карта getExportedCustomBubblingEventTypeConstants () {
    върнете MapBuilder
            .строител()
            .слагам(
                    "При зареждане",
                    MapBuilder.of ("phasedRegistrationNames", MapBuilder.of ("балон", "onLoad"))
            )
            .слагам(
                    "OnError",
                    MapBuilder.of ("phasedRegistrationNames", MapBuilder.of ("балон", "onError"))
            )
            .build ();
}

Изпълнението на моста е готово! Единственото, което остава да направите, е да внедрите PDFViewer.java. Използвах внедряването на AndroidPdfViewer и окончателното решение, което можете да намерите в gitlab (https://github.com/rumax/react-native-PDFView).

Резултати

Изпълнението на моста и PDF Viewer е готово. Определете документа, който искате да направите:

<Преглед на стил = {styles.container}>
   console.log ('onError', грешка)}
    onLoad = {() => console.log ('onLoad')}
    resource = "http://www.pdf995.com/samples/pdf.pdf" />

..заредете приложението и вместо зелен правоъгълник ще получите PDF документ:

Резултати от PDF Viewer