nativescript-community / ui-image

Advanced and efficient image display plugin which uses Fresco (Android) and SDWebImage (iOS) to implement caching, placeholders, image effects, and much more.
Apache License 2.0
36 stars 9 forks source link

Cannot set property 'imageWidth' of null #42

Closed markosole closed 3 years ago

markosole commented 3 years ago

I am having problems with Android (for now) running on device. Error below was thrown randomly. It does not happen all the time. Once images are loaded and cashed, it works fine. I am not sure what is causing it. Plus I have to test it on different devices. Looks like that imageInfo != null isn't doing it's job (...\node_modules\@nativescript-community\ui-image\image.android.js) line 250

System.err: An uncaught Exception occurred on "main" thread.
System.err: Calling js method onFinalImageSet failed
System.err: TypeError: Cannot set property 'imageWidth' of null

Which platform(s) does your issue occur on?

Please, provide the following version numbers that your issue occurs with:

Please, tell us how to recreate the issue in as much detail as possible.

Example of loaded image in view:

<img:Img row="2" col="0" finalImageSet="onFinalImageSet" failure="onFailure" height="100%" width="100%" colSpan="1" placeholderImageUri="res://nemaslike" failureImageUri="res://nemaslike" progressiveRenderingEnabled="true" aspectRatio="0.754" showProgressBar="true" progressBarColor="#FFD9D9" fadeDuration="300" src="{{ 'https://mydomain.com/' + file_url }}"/> 

Is there any code involved?

Temp solution

Changing source on line 248: ...\node_modules\@nativescript-community\ui-image\image.android.js

I've commented out checks for dimensions and it stopped throwing build errors.

updateViewSize(imageInfo) {
    const draweeView = this.nativeViewProtected;
    if (imageInfo != null) {
        //draweeView.imageWidth = imageInfo.getWidth();
        //draweeView.imageHeight = imageInfo.getHeight();
    }
    if (!this.aspectRatio && imageInfo != null) {
        const ratio = imageInfo.getWidth() / imageInfo.getHeight();
        draweeView.setAspectRatio(ratio);
    }
    else if (this.aspectRatio) {
        //draweeView.setAspectRatio(this.aspectRatio);
    }
    else {
        draweeView.setAspectRatio(0);
    }
}

Anyone else had this problems before? - I did not have it on NS6, there was nativescript-image plugin, which was working fine.

Thanks

farfromrefug commented 3 years ago

@markosole there not enough data to actually fix the issue. The issue is with nativeViewProtected being null. This should not happen. Could you provide a repro example?

markosole commented 3 years ago

Hi Martin, thanks for reply.

I can't share full repo, but here is example of that specific part where image is loaded

<GridLayout rows="*" xmlns:lv="nativescript-ui-listview" height="100%">        
        <lv:RadListView id="listView" row="1" items="{{ sviArtikli }}" marginRight="-2">
            <lv:RadListView.listViewLayout>
                <lv:ListViewGridLayout scrollDirection="Vertical" spanCount="2" />
            </lv:RadListView.listViewLayout>
            <lv:RadListView.itemTemplate>
                <GridLayout rows="*" backgroundColor="White">
                    <Card:CardView margin="3" width="95%" height="auto" item="{{ virtuemart_product_id }}" ripple="false" backgroundColor="#fff"  shadowRadius="2" shadowColor="#c3c3c3" mojIndex="{{ id_index }}" tap="detaljiArtikla">
                        <GridLayout rows="20,30,160,50,35,30" columns="*">

                                    <Label row="0" col="0" class="cmshop-artikal-kategorija" text="{{ category_name }}"></Label>                                    
                                    <Label row="1" col="0" class="cmshop-artikal-proizvodjac" text="{{ mf_name }}"></Label>
                                    <img:Img row="2" col="0" class="lista-artikala-slika" finalImageSet="onFinalImageSet" failure="onFailure" height="100%" width="100%" colSpan="1" placeholderImageUri="res://nemaslike" failureImageUri="res://nemaslike" progressiveRenderingEnabled="false" aspectRatio="0.754" showProgressBar="false" progressBarColor="#FFD9D9" fadeDuration="300" src="{{ 'https://dev.cmshop.ba/' + file_url }}"/> 
                                    <Label row="3" col="0" class="cmshop-artikal-naziv" text="{{ product_name }}"></Label>

                        </GridLayout>                        
                    </Card:CardView>
                </GridLayout>
            </lv:RadListView.itemTemplate>
        </lv:RadListView>
</GridLayout>

There are different factors which could effect image loading. I did not have this problem before (2y ago when app was initially built). It's only recently on NS8 and migration of all plugins etc. The device I am testing on haven't been changed or updated.

This view loads around 80-120 articles with images. I am using placeholder from local res. As said previously, I am using that temp fix by commenting those line where image dimension were checked. It does not crash all the time, so I believe it's something to do with cashed / not-cashed images and their sizes.

Is there any way I can "debug" this and see what's going on?

farfromrefug commented 3 years ago

@markosole without a sample repro i cant reproduce it. First you are using radlistview which is far too complicated. If you can you should drop it and use an alternative. We could see if this is still happening there. Thinking it could be image being loaded while the view has been destroyed.

markosole commented 3 years ago

You are right, it is robust but I could not have two columns in ListView with anything else but RadListView. If there is an alternative out there, please share it with me. I'll try to replace it with ListView and see how it goes.

Another thing I've noticed and it's happening only on view with images. When view is loaded (pages navigated to this view) and I just start with scroll, it creates some lag of 50-100ms and it's noticeable every time. I believe it's placeholderImageUri being loaded. Once it's loaded, I can scroll up and down with no lag. I've noticed this lag before and in ScrollView / ListView as well, it's not only now in RadListView.

I'll try to find out when updateViewSize(imageInfo) is fired and what is its output (imageInfo) in console.

BTW: once I begin scrolling, I can see warning:

Warning: WeakRef<Image> was GC and no 'release' callback will be raised.

Thanks!

farfromrefug commented 3 years ago

@markosole try to use @nativescript-community/ui-collectionview About the placeholder yes might be an issue is the image is big. You can instead (for now) use another image view for the place holder and hide it when the image is loaded. BTW this would be much more efficient in a list view because the placeholder image would be loaded like 10 times and that s it!

markosole commented 3 years ago

This looks promising, I will give it a try and se how it goes. Idea for different placeholder image is good as well. I'll try that too. Thanks a lot 😊

markosole commented 3 years ago

Hi @farfromrefug here is update on this.

First things first. I've removed placeHolder image and it does not change a thing, app still crashing. Interesting is that I can see images loaded in the view and like 300ms later app crashes.

As you suggested, I tried with community collectionview and no difference what so ever. I have to use RadListView for other reasons (select and deselect features). I was having problem with selecting one item on the list and when I scroll down, other item got selected too (rendered as selected). Same thing is happening with RadListView and community collectionview.

RadListView gives me option to deselect all items and I trigger it by startScroll. Anyway, that's out of this topic scope.

I did further testing with this:

updateViewSize(imageInfo) {
    const draweeView = this.nativeViewProtected;
    if (imageInfo != null) {
        // MARKO 
        // draweeView.imageWidth = imageInfo.getWidth();
        // draweeView.imageHeight = imageInfo.getHeight();
        console.log("## Width: " + imageInfo.getWidth());
        console.log("## Height: " + imageInfo.getHeight());
    }
    if (!this.aspectRatio && imageInfo != null) {
        const ratio = imageInfo.getWidth() / imageInfo.getHeight();
        draweeView.setAspectRatio(ratio);
    }
    else if (this.aspectRatio) {
        // MARKO 
        draweeView.setAspectRatio(this.aspectRatio);
    }
    else {
        draweeView.setAspectRatio(0);
    }
}

Where console log shows image size properly, including aspectRatio if printed in console.

Than I've added dimensions manually (same which console log showed.

draweeView.imageWidth = 600;
draweeView.imageHeight = 600;

App would crash if any value is assigned to one of draweeView.imageWidth , draweeView.imageHeight. I have another view which has list of 10 items and that one does not crash the app when loaded. Look like it's acting strange with list of 50+ items, even if they are not rendered in the view.

Any ides how could I test it further?

farfromrefug commented 3 years ago

@markosole thanks for testing. You need to create a repro sample. Otherwise i cant help. If it the same with colletionview, create one with it, the debug logs will be much much simpler. You can find me on discord if you want to chat

markosole commented 3 years ago

Hi @farfromrefug , I've created new project form template and installed only two plugins needed for this View to work properly. It does not crash and works just fine. It has to be something in my original project - which is migrated from NS6 to NS7 and than NS8.

Here is the rest of error log received on crash:

System.err: An uncaught Exception occurred on "main" thread.
System.err: Calling js method onFinalImageSet failed
System.err: TypeError: Cannot set property 'imageWidth' of null
System.err:
System.err: StackTrace:
System.err: updateViewSize(file: node_modules\@nativescript-community\ui-image\image.android.js:252:0)
System.err:     at onFinalImageSet(file: node_modules\@nativescript-community\ui-image\image.android.js:400:0)
System.err:     at com.tns.Runtime.callJSMethodNative(Native Method)
System.err:     at com.tns.Runtime.dispatchCallJSMethodNative(Runtime.java:1302)
System.err:     at com.tns.Runtime.callJSMethodImpl(Runtime.java:1188)
System.err:     at com.tns.Runtime.callJSMethod(Runtime.java:1175)
System.err:     at com.tns.Runtime.callJSMethod(Runtime.java:1153)
System.err:     at com.tns.Runtime.callJSMethod(Runtime.java:1149)
System.err:     at com.tns.gen.com.facebook.drawee.controller.ControllerListener.onFinalImageSet(ControllerListener.java:31)
System.err:     at com.facebook.drawee.controller.AbstractDraweeController.reportSuccess(AbstractDraweeController.java:810)
System.err:     at com.facebook.drawee.controller.AbstractDraweeController.onNewResultInternal(AbstractDraweeController.java:633)
System.err:     at com.facebook.drawee.controller.AbstractDraweeController.access$100(AbstractDraweeController.java:56)
System.err:     at com.facebook.drawee.controller.AbstractDraweeController$2.onNewResultImpl(AbstractDraweeController.java:567)
System.err:     at com.facebook.datasource.BaseDataSubscriber.onNewResult(BaseDataSubscriber.java:49)
System.err:     at com.facebook.datasource.AbstractDataSource$1.run(AbstractDataSource.java:197)
System.err:     at android.os.Handler.handleCallback(Handler.java:873)
System.err:     at android.os.Handler.dispatchMessage(Handler.java:99)
System.err:     at android.os.Looper.loop(Looper.java:193)
System.err:     at android.app.ActivityThread.main(ActivityThread.java:6863)
System.err:     at java.lang.reflect.Method.invoke(Native Method)
System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 

I'll have to investigate it further, maybe re-create project entirely from scratch and template from NS8. I've tried something after noticing that onFinalImageSet function throws an error and on the line 400 (check image below). I've commented that line 400 where image size is updated, probably after loading/rendering images in View.

This stops app from crashing and other parts of code can stay intact. This is my temp fix for now until I find out wat is causing this problem.

image

farfromrefug commented 3 years ago

@markosole did you find the source of your issue?

markosole commented 3 years ago

No yet, I'll try with creating new project and see how it goes from there. It is interesting and should not be happening (randomly too). Could be memory issue. It's hard to say... I will update this post once I find it. For now, temp fix works.

farfromrefug commented 3 years ago

@markosole should be fixed in 4.0.24

markosole commented 3 years ago

@farfromrefug thanks for updates on this. I'll try it and see how it goes. I am glad we addressed it and I am not alone :) I am looking forward to contribute. Cheers!