Можно ли объединить GUI made with react native с служебными методами из собственного кода (kotlin)? - PullRequest
5 голосов
/ 17 июня 2020

У меня есть приложение, которое было полностью создано с использованием react native. Это в значительной степени список задач, это структура:

<SafeAreaView style={styles.container}>
        <Text style={styles.title} >Registro de pacientes</Text>
        {loading && (
          <ActivityIndicator
            style={styles.loading}
            size="large"
            color="#0066ff"
          />
        )}
        {!loading && (
          <ListaPacientes  
            pacientes={pacientes} 
            onUpdate={this.handleUpdate}
          />
        )}
      </SafeAreaView>

А вот список:

<SectionList
    sections={
      pacientes && pacientes.length ? 
      [
        {title: "Pacientes sin registrar", data: pacientes.filter(paciente => !paciente.done)},
        {title: "Pacientes registrados", data: pacientes.filter(paciente => paciente.done)}
      ] : []
    }
    keyExtractor={paciente => paciente.id}
    renderItem={({item}) => renderItem(item)}
    renderSectionHeader={renderSectionHeader}
    style={styles.container}
    ItemSeparatorComponent={renderSeparator}
    ListEmptyComponent={renderEmptyComponent}
    stickySectionHeadersEnabled={true}
  />

Это берет список клиентов и отображает их имена. При нажатии они удаляются из списка. Очень просто.

Дело в том, что список клиентов нужно читать из файла csv и после нажатия обновлять csv. У меня уже есть код, который это делает. Тем не менее, он написан в kotlin (он был закодирован для другого проекта).

Вместо того, чтобы снова выполнять всю выборку / чтение / обработку / обновление данных в react native, могу ли я как-то использовать kotlin код уже есть? Если да, не забудьте предоставить пример того, как это будет сделано?

EDIT: Чтобы уточнить, у меня есть метод kotlin, который возвращает ArrayList строк с именами, которые я хочу сохранить в списке. Как я могу вызвать этот метод из javascript, получить массив и использовать его в качестве источника данных для моего списка разделов?.

lateinit var pacientes: Array<String>

@ReactMethod
fun getListaPacientes() : Array<String> {
    return pacientes
}

Что-то вроде этого?


  var res = []
  res = ListaPacientesModulo.getListaPacientes()

Спасибо вы.

Ответы [ 2 ]

3 голосов
/ 22 июня 2020

Я решил проблему следующим образом:

Во-первых, оказалось, что вы не можете использовать собственные модули, если используете expo, поэтому мне пришлось его извлечь.

Во-вторых, чтобы использовать kotlin, вы должны установить плагин вручную (что вы можете сделать, но я решил, что это не стоит хлопот, поэтому я использовал java вместо этого)

Когда дело доходит до код, вам нужно использовать «WritableArray» и «WritableMap».

private static WritableMap convertJsonToMap(JSONObject jsonObject) throws JSONException {
    WritableMap map = new WritableNativeMap();

    Iterator<String> iterator = jsonObject.keys();
    while (iterator.hasNext()) {
        String key = iterator.next();
        Object value = jsonObject.get(key);
        if (value instanceof JSONObject) {
            map.putMap(key, convertJsonToMap((JSONObject) value));
        } else if (value instanceof Boolean) {
            map.putBoolean(key, (Boolean) value);
        } else if (value instanceof Integer) {
            map.putInt(key, (Integer) value);
        } else if (value instanceof Double) {
            map.putDouble(key, (Double) value);
        } else if (value instanceof String) {
            map.putString(key, (String) value);
        } else {
            map.putString(key, value.toString());
        }
    }
    return map;
}

Все методы реакции должны возвращать void, использовать обещания или обратные вызовы для связи с реакцией

@ReactMethod
public void readCSV(Promise promise) {

    //Load the list
    for(int i = 0; i < source.size(); i++) {
        this.listWithPeople.add(new Person(source.get(i), startTimes.get(i)));
    }

    //Pepare the map
    WritableArray defList = new WritableNativeArray();
    Gson g = new Gson();

    for(Person p : this.listWithPeople) {
        JSONObject jo = new JSONObject(g.toJson(p));
        WritableMap wm = convertJsonToMap(jo);
        defList.pushMap(wm);
    }


    promise.resolve(defList);

}

Наконец, в вашем. js файле:

import { NativeModules } from 'react-native';

const { NativeModuleName } = NativeModules;

const getPacientes = async () => {
    var peopleList = []

    var res = await NativeModuleName.readCSV()

    for(var i = 0; i < res.length; i++) {
        peopleList.push(newPerson({ name: res[i].name, star: res[i].date, done: false }))
    }

    return peopleList
}

В части android вам также понадобится этот класс:

ModuleNamePackage. java

public class ModuleNamePackage implements ReactPackage {
    @NonNull
    @Override
    public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
        List<NativeModule> nativeModules = new ArrayList<>();
        nativeModules.add(new NativeModuleName(reactContext));
        return nativeModules;
    }

    @NonNull
    @Override
    public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

И внутри MainApplication. java, вам нужно добавить свой пакет в список пакетов:

private final ReactNativeHost mReactNativeHost =
      new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
          return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          // Packages that cannot be autolinked yet can be added manually here, for example:
          // packages.add(new MyReactNativePackage());
            packages.add(new ModuleNamePackage());
          return packages;
        }

        @Override
        protected String getJSMainModuleName() {
          return "index";
        }
      };
0 голосов
/ 18 июня 2020

Предполагая, что ваш код Kotlin хорошо построен, ie, каждый метод отделен от пользовательского интерфейса, вы можете создать мост от react-native до Kotlin.

Вам необходимо создать пакет, модуль и ваш класс Bridge.

import com.facebook.react.bridge.ReactMethod

class CsvManager(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {

    // the bridge 
    @ReactMethod
    fun update(csvUrl: String, data: List<String>) {
        // your code to load or update the CSV
    }
}

В вашем топ-проекте создайте новый JS как kotlinCsv.js:

import { NativeModules } from 'react-native'
module.exports = NativeModules.CsvModule

в любом месте вашего приложения:

import KotlinCsvUpdater from './kotlinCsv'

let myArray = []
KotlinCsvUpdater.update('pathToMyFile', myArray)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...