williamchart icon indicating copy to clipboard operation
williamchart copied to clipboard

kotlin.UninitializedPropertyAccessException: lateinit property chartConfiguration has not been initialized

Open ugurcany opened this issue 4 years ago • 10 comments

I'm using LineChartView in a custom view, and using that custom view in an item view of a RecyclerView. Each rv item has a different number of entries set using show(...) in onBindViewHolder(...) as expected. However, when I scroll down, I get the following error and app crashes:

Process: com.myapp.app, PID: 16397
    kotlin.UninitializedPropertyAccessException: lateinit property chartConfiguration has not been initialized
        at com.db.williamchart.renderer.LineChartRenderer.draw(LineChartRenderer.kt:103)
        at com.db.williamchart.view.AxisChartView.onDraw(AxisChartView.kt:118)
        at android.view.View.draw(View.java:22350)
        at android.view.View.updateDisplayListIfDirty(View.java:21226)
        at android.view.View.draw(View.java:22081)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at androidx.constraintlayout.widget.ConstraintLayout.dispatchDraw(ConstraintLayout.java:1882)
        at android.view.View.updateDisplayListIfDirty(View.java:21217)
        at android.view.View.draw(View.java:22081)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at androidx.constraintlayout.widget.ConstraintLayout.dispatchDraw(ConstraintLayout.java:1882)
        at android.view.View.draw(View.java:22353)
        at android.view.View.updateDisplayListIfDirty(View.java:21226)
        at android.view.View.draw(View.java:22081)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at androidx.recyclerview.widget.RecyclerView.drawChild(RecyclerView.java:5030)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at android.view.View.draw(View.java:22353)
        at androidx.recyclerview.widget.RecyclerView.draw(RecyclerView.java:4429)
        at android.view.View.updateDisplayListIfDirty(View.java:21226)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
        at android.view.View.updateDisplayListIfDirty(View.java:21186)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
        at android.view.View.updateDisplayListIfDirty(View.java:21186)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
        at android.view.View.updateDisplayListIfDirty(View.java:21186)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
        at android.view.View.updateDisplayListIfDirty(View.java:21186)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
        at android.view.View.updateDisplayListIfDirty(View.java:21186)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
        at android.view.View.updateDisplayListIfDirty(View.java:21186)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
        at android.view.View.updateDisplayListIfDirty(View.java:21186)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)

Running device: Pixel 4 emulator, Android API 30

ugurcany avatar Nov 16 '20 18:11 ugurcany

I've done that as a workaround in my fragment (for DonutChartView). How it works? The chartConfiguration lateinit property of ChartRenderer is initialized in show() and animate() methods of DonutChartView, so you have to invoke one of these methods before View's onDraw(), because chartConfiguration is accessed in onDraw().


override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return super.onCreateView(inflater, container, savedInstanceState).also { view ->
            view?.findViewById<DonutChartView>(R.id.donutChartView)
                ?.show(listOf())
        }
    }

swistak7171 avatar Dec 01 '20 18:12 swistak7171

@swistak7171 Unfortunately this solution doesn't work for charts in recyclerview. I'm doing the following as workaround: In my custom rv item view that includes chart as child, I override the following methods:

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        binding.chart.show(values)
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        binding.chart.show(listOf())
    }

This resolves the issue kotlin.UninitializedPropertyAccessException: lateinit property chartConfiguration has not been initialized .

@diogobernardino any comment from your side would be great!

ugurcany avatar Dec 02 '20 07:12 ugurcany

I couldn't yet reproduce it. Can someone provide a bit more context (e.g. data, rv adapter, rv view holder)?

diogobernardino avatar Dec 20 '20 21:12 diogobernardino

I have the same problem as @swistak7171 @ugurcany, but I am using the DonutChartView. I am using the new Compose UI Toolkit (the DonutChartView is wrapped in AndroidView) and the crashes happen in android 10 and 11 in the Android 9 I have no issues.

rcaceiro avatar Jan 08 '21 11:01 rcaceiro

@diogobernardino, I hope these details will help you . I'm using the LineChartView . The App crashes when scrolling in my RecyclerView inside of a Fragment.

Java

@NonNull
    @Override
    public AssetsHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.assets_item,parent,false);
        AssetsHolder assetsHolder = new AssetsHolder(itemView);
        return assetsHolder;
    }


    @Override
    public void onBindViewHolder(@NonNull final AssetsHolder holder, int position) {
        String currentName = OurData.items.get(position);
        HashMap<String, List<Pair<String,Float>>> allcharts = OurData.chartMap;
        if(allcharts != null){
            List<Pair<String,Float>> list = allcharts.get(currentName);
            if(list != null) {
                holder.lineChartView.show(list);
            }
        }

    }

XML.


 <com.db.williamchart.view.LineChartView
                    android:id="@+id/chartView"
                    android:layout_width="92dp"
                    android:layout_height="58dp"
                    android:layout_toStartOf="@id/remove"
                    android:layout_marginEnd="4dp"
                    android:layout_marginTop="4dp"
                    android:layout_marginRight="4dp"
                    android:layout_marginLeft="10dp"
                    android:layout_toEndOf="@id/name_Frame"
                    android:layout_marginStart="10dp"
                    app:chart_lineColor="#FF163A9A"
                    app:chart_smoothLine="true"
                    app:chart_axis="none"
                    app:chart_gridEffect="dotted"
                    android:background="?attr/colorPrimaryDark"
                    android:layout_marginBottom="4dp"
                    android:layout_centerVertical="true"
                    android:layout_centerHorizontal="true"
            />

Error

kotlin.UninitializedPropertyAccessException: lateinit property innerFrame has not been initialized
        at com.db.williamchart.renderer.LineChartRenderer.processTouch(LineChartRenderer.kt:180)
        at com.db.williamchart.view.AxisChartView.onTouchEvent(AxisChartView.kt:144)
        at android.view.View.dispatchTouchEvent(View.java:12513)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3024)

build.gradle

dependencies {

implementation 'com.diogobernardino:williamchart:3.10.1'

}

AnregendSchoenerelch avatar May 03 '21 13:05 AnregendSchoenerelch

Having a second look at the exceptions, my guess is that the init block of chart views can be executed before a touch event or onDraw Unfortunately I still couldn't come up with a sample project to reproduce the crash. @AnregendSchoenerelch I tried using your snippets but I think it's not enough to see the crash. Any chance I can have a repository with a sample project where I can reproduce it? Thanks in advance.

diogobernardino avatar Jul 15 '21 19:07 diogobernardino

Same Issue using DonutChartView with data binding. Only XML code

                                <com.db.williamchart.view.DonutChartView
                                    android:layout_width="100dp"
                                    android:layout_height="100dp"
                                    app:chart_donutRoundCorners="true"
                                    android:id="@+id/donut_chart"
                                    app:chart_donutThickness="12dp"
                                    app:chart_donutTotal="100"
                                    app:layout_constraintLeft_toLeftOf="parent"
                                    app:layout_constraintRight_toRightOf="parent"
                                    app:layout_constraintTop_toBottomOf="parent"
                                    app:layout_constraintTop_toTopOf="parent" />

Data binding:

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        viewDataBinging = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
        rootView = viewDataBinging.getRoot();
        return rootView;
    }

dehghanGit avatar Jul 17 '21 16:07 dehghanGit

Same issue. Using chart inside onViewCreated/onResume of the viewPager fragment. Lateinit property innerFrame has not been initialized. The chart is drawn blank despite getting the data populated. Trying to click a blank chart results in a crash. Clearly a library issue not initializing properly. And using lateinit was a bad idea to begin with. Using databinding. Populating the chart in onResume()

Nek-12 avatar Nov 16 '21 05:11 Nek-12

I faced the same exception on Andorid11 with LineChart. I share this proj (https://github.com/vicpls/WChart) and Log.txt

vicpls avatar Nov 19 '21 20:11 vicpls

i think it happen because the graph is init in hurry time. i use graph in ViewPager2

i solved it by give some delay

bind.barChart.postDelayed(Runnable { bind.barChart.show(datas) }, 5)

wiztensai avatar Apr 16 '22 05:04 wiztensai