java.lang.ClassCastException:com.myapp.MainActivity不能强制转换为co



我正试图在android上用fragment创建一个native ui

CealScanQrView.kt
class CealScanQrView(context: Context): FrameLayout(context) {
...
//Contains all the logic of integrating camerax, check below code repo to see the full source code 
...
//Now while submitting the data from native side to react-native I get error
val reactContext = context as ReactContext ///This line causes error and makes my app crash
reactContext
.getJSModule(RCTEventEmitter::class.java)
.receiveEvent(id, topChange, event)
}
CealScanQrFragment.kt
class CealScanQrFragment: Fragment() {
private lateinit var cealScanQrView: CealScanQrView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
cealScanQrView = CealScanQrView(requireNotNull(context))
return cealScanQrView // this CustomView could be any view that you want to render
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// do any logic that should happen in an `onCreate` method, e.g:
cealScanQrView.setUpCamera(requireActivity())
}
override fun onDestroy() {
super.onDestroy()
cealScanQrView.destroyCamera()
}
}

CealScanQrViewManager.kt
class CealScanQrViewManager(
private val reactContext: ReactApplicationContext
) : ViewGroupManager<FrameLayout>() {
private val cealScanQrView = "CealScanQrView"
private val topChange = "topChange"
private val phasedRegistrationNames = "phasedRegistrationNames"
private val bubbled = "bubbled"
private val onChange = "onChange"
private val create = "create"
companion object {
private const val COMMAND_CREATE = 1
}
private var propWidth: Int? = null
private var propHeight: Int? = null
override fun getName() = cealScanQrView
override fun createViewInstance(reactContext: ThemedReactContext) = FrameLayout(reactContext)
override fun getCommandsMap() = mapOf("create" to COMMAND_CREATE)
override fun receiveCommand(root: FrameLayout, commandId: String?, args: ReadableArray?) {
super.receiveCommand(root, commandId, args)
val reactNativeViewId = requireNotNull(args).getInt(0)
when (commandId?.toInt()) {
COMMAND_CREATE -> createFragment(root, reactNativeViewId)
}
}
private fun createFragment(root: FrameLayout, reactNativeViewId: Int) {
val parentView = root.findViewById<ViewGroup>(reactNativeViewId)
setupLayout(parentView)
val myFragment = CealScanQrFragment()
val activity = reactContext.currentActivity as FragmentActivity
activity.supportFragmentManager
.beginTransaction()
.replace(reactNativeViewId, myFragment, reactNativeViewId.toString())
.commit()
}
private fun setupLayout(view: View) {
Choreographer.getInstance().postFrameCallback(object: Choreographer.FrameCallback {
override fun doFrame(frameTimeNanos: Long) {
manuallyLayoutChildren(view)
view.viewTreeObserver.dispatchOnGlobalLayout()
Choreographer.getInstance().postFrameCallback(this)
}
})
}
@ReactPropGroup(names = ["width", "height"], customType = "Style")
fun setStyle(view: FrameLayout, index: Int, value: Int) {
if (index == 0) propWidth = value
if (index == 1) propHeight = value
}
private fun manuallyLayoutChildren(view: View) {
// propWidth and propHeight coming from react-native props
val width = requireNotNull(propWidth)
val height = requireNotNull(propHeight)
view.measure(
View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY))
view.layout(0, 0, width, height)
}

override fun getExportedCustomBubblingEventTypeConstants(): Map<String, Any> {
return mapOf(
topChange to mapOf(
phasedRegistrationNames to mapOf(
bubbled to onChange
)
)
)
}
}

val reactContext = context as ReactContext导致应用程序崩溃并抛出错误,称

java.lang.ClassCastException: com.myapp.MainActivity cannot be cast to com.facebook.react.bridge.ReactContext

什么样的context我应该从我的fragment传递到Native UI View,这样我就可以使用getJSModule方法发送数据

完整的源代码在这里

不能将android的Context类强制转换为ReactContext。

如果您将在View类中使用reactContext,那么您可以从ViewManager传递reactContext实例-->片段-->查看

1-这样写接口:

interface ReactContextProvider {
fun provideReactContext(): ReactApplicationContext
}

2-在CealScanQrViewManager类中实现此接口:

class CealScanQrViewManager(
private val reactContext: ReactApplicationContext
) : ViewGroupManager<FrameLayout>(), ReactContextProvider {
...
override fun provideReactContext(): ReactApplicationContext {
return reactContext
}
...
}

3-将reactContext Provider添加到CealScanQrFragment

var reactContextProvider: ReactContextProvider? = null

4-将此接口传递给CealScanQrViewManager类上的createFragment函数中的CealScanQ rFragment类。

val myFragment = CealScanQrFragment()
myFragment.reactContextProvider = this

5-在CealScanQrView类中定义变量:

var reactContextProvider: ReactContextProvider? = null

6-将此变量传递到CealScanQrFragmentonCreateView函数上的CealScanQ rView实例:

cealScanQrView = CealScanQrView(requireNotNull(context))
cealScanQrView.reactContextProvider = reactContextProvider

7-在下面的视图中使用您的reactContextProvider:

reactContextProvider?.provideReactContext()?.let { reactContext -->
reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(id, topChange, event)
}

最新更新