【问题标题】:Well working Java code is causing kotlin.TypeCastException: null cannot be cast to non-null type when converted to Kotlin code运行良好的 Java 代码导致 kotlin.TypeCastException: null cannot be cast to non-null type when convert to Kotlin code
【发布时间】:2020-05-14 04:26:39
【问题描述】:

我必须为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


    【解决方案1】:

    第一个问题是您尝试将castnullable 值(params.layoutAnimationParameters)转换为non null type,这会导致null pointer exceptionparams.layoutAnimationParametersnull

    要解决这个问题,请使用 kotlin 的 safe cast operator (as?),它尝试将 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)
        }
    }
    

    【讨论】:

      【解决方案2】:

      像这样使用它:

      val animationParams =
                      params.layoutAnimationParameters as? GridLayoutAnimationController.AnimationParameters
      

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

      animationParams?.count = count
      

      【讨论】:

        猜你喜欢
        • 2017-10-20
        • 2022-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-11
        • 1970-01-01
        相关资源
        最近更新 更多