簡體   English   中英

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

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

我正在嘗試在android上創建帶有fragmentnative 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 class 轉換為 ReactContext。

如果您將在 View class 中使用 reactContext,那么您可以從 ViewManager --> Fragment --> View 傳遞 ReactContext 實例

1 - 編寫這樣的界面:

interface ReactContextProvider {
    fun provideReactContext(): ReactApplicationContext
}

2 - 在您的CealScanQrViewManager class 中實現此接口:

class CealScanQrViewManager(
    private val reactContext: ReactApplicationContext
) : ViewGroupManager<FrameLayout>(), ReactContextProvider {
...

    override fun provideReactContext(): ReactApplicationContext {
        return reactContext
    }

...
}

3 - 將 reactContextProvider 添加到CealScanQrFragment class

var reactContextProvider: ReactContextProvider? = null

4 - 將此接口傳遞給CealScanQrViewManager class 上的createFragment function 中的CealScanQrFragment class。

val myFragment = CealScanQrFragment()
myFragment.reactContextProvider = this

5 - 在您的CealScanQrView class 中定義一個變量:

var reactContextProvider: ReactContextProvider? = null

6 - 將此變量傳遞給 CealScanQrFragment 上onCreateView function 上的CealScanQrView實例

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

7 - 在 View 中使用您的 reactContextProvider,如下所示:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM