运行良好的Java代码导致kotlin.TypeCastException:转换为Kotlin代码时,不能将null强制转换为非null类型

问题描述 投票:0回答:2

我必须给RecyclerView的项目添加动画,并按给定的打击来创建CustomGridRecyclerView

public class CustomGridRecyclerView extends RecyclerView {

    public CustomGridRecyclerView(Context context) {
        super(context);
    }

    public CustomGridRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomGridRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setLayoutManager(LayoutManager layout) {
        if (layout instanceof GridLayoutManager) {
            super.setLayoutManager(layout);
        } else {
            throw new ClassCastException("This recyclerview should use grid layout manager as the layout manager");
        }
    }

    @Override
    protected void attachLayoutAnimationParameters(View child, ViewGroup.LayoutParams params, int index, int count) {

        if (getAdapter() != null && getLayoutManager() instanceof GridLayoutManager) {

            GridLayoutAnimationController.AnimationParameters animationParams =
                    (GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters;

            if (animationParams == null) {
                animationParams = new GridLayoutAnimationController.AnimationParameters();
                params.layoutAnimationParameters = animationParams;
            }

            int columns = ((GridLayoutManager) getLayoutManager()).getSpanCount();

            animationParams.count = count;
            animationParams.index = index;
            animationParams.columnsCount = columns;
            animationParams.rowsCount = count / columns;

            final int invertedIndex = count - 1 - index;
            animationParams.column = columns - 1 - (invertedIndex % columns);
            animationParams.row = animationParams.rowsCount - 1 - invertedIndex / columns;

        } else {
            super.attachLayoutAnimationParameters(child, params, index, count);
        }
    }
}

效果很好,但是我想在Kotlin中使用以下代码在其他应用程序中实现相同的功能:

class CustomGridRecyclerView : RecyclerView {
    constructor(context: Context?) : super(context!!)
    constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(
        context!!,
        attrs,
        defStyle
    )

    override fun setLayoutManager(layout: LayoutManager?) {
        if (layout is GridLayoutManager) {
            super.setLayoutManager(layout)
        } else {
            throw ClassCastException("This RecyclerView should use GridLayoutManager as the layout manager")
        }
    }

    override fun attachLayoutAnimationParameters(
        child: View?,
        params: ViewGroup.LayoutParams,
        index: Int,
        count: Int
    ) {
        if (adapter != null && layoutManager is GridLayoutManager) {
            //val
            val animationParams =
                params.layoutAnimationParameters as GridLayoutAnimationController.AnimationParameters // CustomGridRecyclerView.kt:38 is the line where kotlin.TypeCastException occurs I have tried with GridLayoutAnimationController.AnimationParameters? as well but never succeeded 
            val columns = (layoutManager as GridLayoutManager?)!!.spanCount
            animationParams.count = count
            animationParams.index = index
            animationParams.columnsCount = columns
            animationParams.rowsCount = count / columns
            val invertedIndex = count - 1 - index
            animationParams.column = columns - 1 - invertedIndex % columns
            animationParams.row = animationParams.rowsCount - 1 - invertedIndex / columns
        } else {
            super.attachLayoutAnimationParameters(child, params, index, count)
        }
    }
}

它给我错误:

kotlin.TypeCastException: null cannot be cast to non-null type android.view.animation.GridLayoutAnimationController.AnimationParameters
        at pk.inlab.app.expenselogger.view.custom.CustomGridRecyclerView.attachLayoutAnimationParameters(CustomGridRecyclerView.kt:38)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3267)
        at android.view.View.draw(View.java:15507)
        at androidx.recyclerview.widget.RecyclerView.draw(RecyclerView.java:4219)
        at android.view.View.updateDisplayListIfDirty(View.java:14384)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at android.view.View.draw(View.java:15507)
        at android.view.View.updateDisplayListIfDirty(View.java:14384)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.drawChild(CoordinatorLayout.java:1246)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at android.view.View.draw(View.java:15507)
        at android.view.View.updateDisplayListIfDirty(View.java:14384)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at android.view.View.updateDisplayListIfDirty(View.java:14376)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at android.view.View.updateDisplayListIfDirty(View.java:14376)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at android.view.View.updateDisplayListIfDirty(View.java:14376)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at android.view.View.updateDisplayListIfDirty(View.java:14376)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchDraw(PhoneWindow.java:2784)
        at android.view.View.draw(View.java:15507)
        at android.widget.FrameLayout.draw(FrameLayout.java:658)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2763)
        at android.view.View.updateDisplayListIfDirty(View.java:14384)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:279)
        at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:285)
        at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:335)
        at android.view.ViewRootImpl.draw(ViewRootImpl.java:2939)
        at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2753)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2367)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1292)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6598)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:800)
        at android.view.Choreographer.doCallbacks(Choreographer.java:603)
        at android.view.Choreographer.doFrame(Choreographer.java:572)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:786)
        at android.os.Handler.handleCallback(Handler.java:815)
        at android.os.Handler.dispatchMessage(Handler.java:104)
        at android.os.L

我如何正确地投射android.view.animation.GridLayoutAnimationController.AnimationParameters

更新

根据下面答案的建议,我更改了代码

   val animationParams =
                params.layoutAnimationParameters as? GridLayoutAnimationController.AnimationParameters
            val columns = (layoutManager as GridLayoutManager?)!!.spanCount
            animationParams!!.count = count

并且得到这个:

kotlin.KotlinNullPointerException
        at pk.inlab.app.expenselogger.view.custom.CustomGridRecyclerView.attachLayoutAnimationParameters(CustomGridRecyclerView.kt:40)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3267)
        at android.view.View.draw(View.java:15507)
        at androidx.recyclerview.widget.RecyclerView.draw(RecyclerView.java:4219)
        at android.view.View.updateDisplayListIfDirty(View.java:14384)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at android.view.View.draw(View.java:15507)
        at android.view.View.updateDisplayListIfDirty(View.java:14384)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.drawChild(CoordinatorLayout.java:1246)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at android.view.View.draw(View.java:15507)
        at android.view.View.updateDisplayListIfDirty(View.java:14384)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at android.view.View.updateDisplayListIfDirty(View.java:14376)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at android.view.View.updateDisplayListIfDirty(View.java:14376)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at android.view.View.updateDisplayListIfDirty(View.java:14376)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at android.view.View.updateDisplayListIfDirty(View.java:14376)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.View.draw(View.java:15204)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3532)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3325)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchDraw(PhoneWindow.java:2784)
        at android.view.View.draw(View.java:15507)
        at android.widget.FrameLayout.draw(FrameLayout.java:658)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2763)
        at android.view.View.updateDisplayListIfDirty(View.java:14384)
        at android.view.View.getDisplayList(View.java:14413)
        at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:279)
        at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:285)
        at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:335)
        at android.view.ViewRootImpl.draw(ViewRootImpl.java:2939)
        at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2753)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2367)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1292)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6598)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:800)
        at android.view.Choreographer.doCallbacks(Choreographer.java:603)
        at android.view.Choreographer.doFrame(Choreographer.java:572)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:786)
        at android.os.Handler.handleCallback(Handler.java:815)
        at android.os.Handler.dispatchMessage(Handler.java:104)
        at android.os.Looper.loop(Looper.java:194)
        at android.app.ActivityThread.main(ActivityThread.java:5631)
        at java.lang
android kotlin android-recyclerview android-gridlayout gridlayoutmanager
2个回答
1
投票

[第一个问题是您尝试将castnullable值(params.layoutAnimationParameters)设置为non null type,当null pointer exceptionparams.layoutAnimationParameters时,这会导致null

为了解决此问题,请使用kotlin的safe cast operatoras?),它尝试将cast的值赋予给定的type,如果不能,则仅返回null

第二个问题是在您的Java代码中,如果params.layoutAnimationParametersnull,则为它分配一个新的GridLayoutAnimationController.AnimationParameters()

if (animationParams == null) {
   animationParams = new GridLayoutAnimationController.AnimationParameters();
   params.layoutAnimationParameters = animationParams;
}

我没有看到您在Kotlin代码中做同样的事情。我已经修改了您的function以使用safe cast和适当的null检查,它应该可以工作。

override fun attachLayoutAnimationParameters(
        child: View?,
        params: ViewGroup.LayoutParams,
        index: Int,
        count: Int
) {
    if (adapter != null && layoutManager is GridLayoutManager) {
        var animationParams =
                params.layoutAnimationParameters as? GridLayoutAnimationController.AnimationParameters 
        if (animationParams == null) {
            animationParams = AnimationParameters()
            params.layoutAnimationParameters = animationParams
        }
        val columns = layoutManager.spanCount
        animationParams.count = count
        animationParams.index = index
        animationParams.columnsCount = columns
        animationParams.rowsCount = count / columns
        val invertedIndex = count - 1 - index
        animationParams.column = columns - 1 - invertedIndex % columns
        animationParams.row = animationParams.rowsCount - 1 - invertedIndex / columns
    } else {
        super.attachLayoutAnimationParameters(child, params, index, count)
    }
}

0
投票

像这样使用它:

val animationParams =
                params.layoutAnimationParameters as? GridLayoutAnimationController.AnimationParameters

然后将访问权限更改为空安全访问,如下所示:

animationParams?.count = count
© www.soinside.com 2019 - 2024. All rights reserved.