Хорошо работающий Java код вызывает kotlin .TypeCastException: ноль не может быть приведен к непустому типу при преобразовании в Kotlin код - PullRequest
0 голосов
/ 28 января 2020

Мне нужно добавить анимацию к элементам 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

Ответы [ 2 ]

2 голосов
/ 28 января 2020

Первая проблема заключается в том, что вы пытаетесь cast обнуляемое значение (params.layoutAnimationParameters) до ненулевого типа , это вызывает null pointer exception при params.layoutAnimationParameters is null.

Чтобы решить эту проблему, используйте kotlin s безопасный оператор приведения (as?), который пытается cast значение для данного type, и если тогда он не может просто вернуть null.

Вторая проблема заключается в том, что в вашем java коде, если params.layoutAnimationParameters равно null, тогда вы назначаете ему новый 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 голосов
/ 28 января 2020

используйте его следующим образом:

val animationParams =
                params.layoutAnimationParameters as? GridLayoutAnimationController.AnimationParameters

И затем измените доступ на нулевой безопасный доступ, например:

animationParams?.count = count
...