Skip to content

Finalize the Kotlinization #3360

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ my-component
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── MyComponent
│ │ └── mycomponent
│ │ ├── MyComponentView.java
│ │ ├── MyComponentViewManagerImpl.java
│ │ └── MyComponentViewPackage.java
Expand All @@ -306,8 +306,12 @@ my-component

The code that should go in the `MyComponentViewManagerImpl.java` and that can be shared between the Native Component and the Fabric Native Component is, for example:

<Tabs groupId="android-language" defaultValue={constants.defaultAndroidLanguage} values={constants.androidLanguages}>
<TabItem value="java">

```java title="example of MyComponentViewManager.java"
package com.MyComponent;
package com.mycomponent;

import androidx.annotation.Nullable;
import com.facebook.react.uimanager.ThemedReactContext;

Expand All @@ -325,10 +329,34 @@ public class MyComponentViewManagerImpl {
}
```

</TabItem>
<TabItem value="kotlin">

```kotlin title="example of MyComponentViewManager.kt"
package com.mycomponent

import com.facebook.react.uimanager.ThemedReactContext

object MyComponentViewManagerImpl {
const val NAME = "MyComponent"
fun createViewInstance(context: ThemedReactContext?) = MyComponentView(context)

fun setFoo(view: MyComponentView, param: String) {
// implement the logic of the foo function using the view and the param passed.
}
}
```

</TabItem>
</Tabs>

Then, the Native Component and the Fabric Native Component can be updated using the function declared in the shared manager.

For example, for a Native Component:

<Tabs groupId="android-language" defaultValue={constants.defaultAndroidLanguage} values={constants.androidLanguages}>
<TabItem value="java">

```java title="Native Component using the ViewManagerImpl"
public class MyComponentViewManager extends SimpleViewManager<MyComponentView> {

Expand Down Expand Up @@ -359,8 +387,34 @@ public class MyComponentViewManager extends SimpleViewManager<MyComponentView> {
}
```

</TabItem>
<TabItem value="kotlin">

```kotlin title="Native Component using the ViewManagerImpl"
class MyComponentViewManager(var context: ReactApplicationContext) : SimpleViewManager<MyComponentView>() {
// Use the static NAME property from the shared implementation
override fun getName() = MyComponentViewManagerImpl.NAME

public override fun createViewInstance(context: ThemedReactContext): MyComponentView =
// static createViewInstance function from the shared implementation
MyComponentViewManagerImpl.createViewInstance(context)

@ReactProp(name = "foo")
fun setFoo(view: MyComponentView, param: String) {
// static custom function from the shared implementation
MyComponentViewManagerImpl.setFoo(view, param)
}
}
```

</TabItem>
</Tabs>

And, for a Fabric Native Component:

<Tabs groupId="android-language" defaultValue={constants.defaultAndroidLanguage} values={constants.androidLanguages}>
<TabItem value="java">

```java title="Fabric Component using the ViewManagerImpl"
// Use the static NAME property from the shared implementation
@ReactModule(name = MyComponentViewManagerImpl.NAME)
Expand Down Expand Up @@ -397,11 +451,40 @@ public class MyComponentViewManager extends SimpleViewManager<MyComponentView>
@ReactProp(name = "foo")
public void setFoo(MyComponentView view, @Nullable String param) {
// static custom function from the shared implementation
MyComponentViewManagerImpl.setFoo(view, param]);
MyComponentViewManagerImpl.setFoo(view, param);
}
}
```

</TabItem>
<TabItem value="kotlin">

```kotlin title="Fabric Component using the ViewManagerImpl"
// Use the static NAME property from the shared implementation
@ReactModule(name = MyComponentViewManagerImpl.NAME)
class MyComponentViewManager(context: ReactApplicationContext) : SimpleViewManager<MyComponentView>(), MyComponentViewManagerInterface<MyComponentView> {
private val delegate: ViewManagerDelegate<MyComponentView> = MyComponentViewManagerDelegate(this)

override fun getDelegate(): ViewManagerDelegate<MyComponentView> = delegate

// Use the static NAME property from the shared implementation
override fun getName(): String = MyComponentViewManagerImpl.NAME

override fun createViewInstance(context: ThemedReactContext): MyComponentView =
// static createViewInstance function from the shared implementation
MyComponentViewManagerImpl.createViewInstance(context)

@ReactProp(name = "foo")
override fun setFoo(view: MyComponentView, text: String) {
// static custom function from the shared implementation
MyComponentViewManagerImpl.setFoo(view, param);
}
}
```

</TabItem>
</Tabs>

For a step-by-step example on how to achieve this, have a look at [this repo](https://github.com/react-native-community/RNNewArchitectureLibraries/tree/feat/back-fabric-comp).

## Unify the JavaScript specs
Expand Down
80 changes: 76 additions & 4 deletions docs/the-new-architecture/backward-compatibility-turbomodules.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ my-module
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── MyModule
│ │ └── mymodule
│ │ ├── MyModuleImpl.java
│ │ └── MyModulePackage.java
│ ├── newarch
Expand All @@ -252,8 +252,11 @@ my-module

The code that should go in the `MyModuleImpl.java`, and that can be shared by the Legacy Native Module and the Turbo Native Module is, for example:

```java title="example of MyModuleImple.java"
package com.MyModule;
<Tabs groupId="android-language" defaultValue={constants.defaultAndroidLanguage} values={constants.androidLanguages}>
<TabItem value="java">

```java title="example of MyModuleImpl.java"
package com.mymodule;

import androidx.annotation.NonNull;
import com.facebook.react.bridge.Promise;
Expand All @@ -271,6 +274,29 @@ public class MyModuleImpl {
}
```

</TabItem>
<TabItem value="kotlin">

```kotlin title="example of MyModuleImpl.kt"
package com.mymodule;

import com.facebook.react.bridge.Promise

class MyModuleImpl {
fun foo(a: Double, b: Double, promise: Promise) {
// implement the logic for foo and then invoke
// promise.resolve or promise.reject.
}

companion object {
const val NAME = "MyModule"
}
}
```

</TabItem>
</Tabs>

Then, the Legacy Native Module and the Turbo Native Module can be updated with the following steps:

1. Create a private instance of the `MyModuleImpl` class.
Expand All @@ -279,13 +305,16 @@ Then, the Legacy Native Module and the Turbo Native Module can be updated with t

For example, for a Legacy Native Module:

<Tabs groupId="android-language" defaultValue={constants.defaultAndroidLanguage} values={constants.androidLanguages}>
<TabItem value="java">

```java title="Native Module using the Impl module"
public class MyModule extends ReactContextBaseJavaModule {

// declare an instance of the implementation
private MyModuleImpl implementation;

CalculatorModule(ReactApplicationContext context) {
MyModule(ReactApplicationContext context) {
super(context);
// initialize the implementation of the module
implementation = MyModuleImpl();
Expand All @@ -305,8 +334,32 @@ public class MyModule extends ReactContextBaseJavaModule {
}
```

</TabItem>
<TabItem value="kotlin">

```kotlin title="Native Module using the Impl module"
class MyModule(context: ReactApplicationContext) : ReactContextBaseJavaModule(context) {
// declare an instance of the implementation and use it in all the methods
private var implementation: MyModuleImpl = MyModuleImpl()

override fun getName(): String = MyModuleImpl.NAME

@ReactMethod
fun foo(a: Double, b: Double, promise: Promise) {
// Use the implementation instance to execute the function.
implementation.foo(a, b, promise)
}
}
```

</TabItem>
</Tabs>

And, for a Turbo Native Module:

<Tabs groupId="android-language" defaultValue={constants.defaultAndroidLanguage} values={constants.androidLanguages}>
<TabItem value="java">

```java title="TurboModule using the Impl module"
public class MyModule extends MyModuleSpec {
// declare an instance of the implementation
Expand All @@ -333,6 +386,25 @@ public class MyModule extends MyModuleSpec {
}
```

</TabItem>
<TabItem value="kotlin">

```kotlin title="TurboModule using the Impl module"
class MyModule(reactContext: ReactApplicationContext) : MyModuleSpec(reactContext) {
// declare an instance of the implementation and use it in all the methods
private var implementation: MyModuleImpl = MyModuleImpl()

override fun getName(): String = MyModuleImpl.NAME

override fun add(a: Double, b: Double, promise: Promise) {
implementation.add(a, b, promise)
}
}
```

</TabItem>
</Tabs>

For a step-by-step example on how to achieve this, have a look at [this repo](https://github.com/react-native-community/RNNewArchitectureLibraries/tree/feat/back-turbomodule).

## Unify the JavaScript specs
Expand Down
Loading