Skip to content

Commit

Permalink
Finalize the Kotlinization (facebook#3360)
Browse files Browse the repository at this point in the history
* Finalize the Kotlinization

* Remove extra imports
  • Loading branch information
cortinico authored Oct 5, 2022
1 parent 3c124e0 commit 911a282
Show file tree
Hide file tree
Showing 4 changed files with 432 additions and 46 deletions.
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

0 comments on commit 911a282

Please sign in to comment.