facebook / fresco

An Android library for managing images and the memory they use.
https://frescolib.org/
MIT License
17.07k stars 3.75k forks source link

Image does not display in SimpleDraweeView when open react-native page for the first time #1683

Closed elyonsaber closed 7 years ago

elyonsaber commented 7 years ago

I wrapped up android native UI component, and integrated it with my react native application. The layout of this component includes SimpleDraweeView `

<com.facebook.drawee.view.SimpleDraweeView
    android:id="@+id/avatar_image"
    android:layout_width="26dp"
    android:layout_height="26dp"
    android:layout_marginTop="6dp"
    android:layout_centerHorizontal="true"
    android:scaleType="centerCrop"
    fresco:failureImageScaleType="fitCenter"
    fresco:placeholderImage="@drawable/gift_box_0"
    fresco:placeholderImageScaleType="centerCrop"
    fresco:roundAsCircle="true" />

` And I set imageUri of SimpleDraweeView dynamically in code:

SimpleDraweeView avatar = (SimpleDraweeView) infoWindow.findViewById(R.id.avatar_image); avatar.setImageURI(UserRepository.getInstance().getUserInfo().getAvatar().getUrl());

However, when I first open the react page, it only shows placeholder image. If I go back to the previous page, and enter this react page again, then the drawee displays the correct image of uri. So do I miss any setting? Or is this the issue of React Native? Thanks!

kirwan commented 7 years ago

Nothing looks obviously wrong from what you've detailed here but I'd be interested where you're setting the URI.

You could compare what you have with the ReactImageView class in React Native. Particularly, I'd suggest looking at where they call maybeUpdateView() which is where they initiate the request.

Beyond that, you might have more luck asking this question on the React Native project as I don't have much experience of working with that.

elyonsaber commented 7 years ago

Thanks for you prompt reply! Just as you mentioned, I thought the problem was caused by that I set the URI, and then add the view to map as a marker, like this:

View infoWindow = layoutInflater.inflate(R.layout.custom_map_location, LL, false);
SimpleDraweeView avatar = (SimpleDraweeView) infoWindow.findViewById(R.id.avatar_image);
avatar.setImageURI(UserRepository.getInstance().getUserInfo().getAvatar().getUrl());
Marker marker = map.addMarker(
new MarkerOptions().position(new LatLng(amapLocation.getLatitude(),amapLocation.getLongitude()))
                           .anchor(0.5f, 1f)
                           .icon(BitmapDescriptorFactory.fromView(infoWindow)));

I should have waited util the loading of image was complete before add it to map as a marker, so I try to set control listener to SimpleDraweeView:

 mControllerListener = new BaseControllerListener<ImageInfo>() {
    @Override
    public void onFinalImageSet(String id,
                       @Nullable final ImageInfo imageInfo,
                       @Nullable Animatable animatable) {
         Marker marker = map.addMarker(
              new MarkerOptions().position(new LatLng(amapLocation.getLatitude(), ampLocation.getLongitude()))        
                                 .anchor(0.5f, 1f)
                                 .icon(BitmapDescriptorFactory.fromView(infoWindow)));
                                }

     @Override
     public void onFailure(String id, Throwable throwable) {
             LogUtil.d(TAG, "on failure");
     }
  };

 DraweeController controller = Fresco.newDraweeControllerBuilder()
                                    .setUri(Uri.parse(UserRepository.getInstance().getUserInfo().getAvatar().getUrl()))
                                    .setControllerListener(mControllerListener)
                                    .setOldController(avatar.getController())
                                    .build();

 avatar.setController(controller);

But this time I found that neither onFinalImageSet nor onFailure was called. So could you plz give me any more suggestion? Great thanks!

elyonsaber commented 7 years ago

The issue is similar to this one in react-native-maps. After several tries, I finally found a way to solve this issue. SimpleDraweeView called onAttach DraweeHolder in onAttachedToWindow() and onStartTemporaryDetach() , so if I just inflate a layout and don't add it to root view to display it, these two methods seems not to be called. I wrote a custom view extends imageView according to docs. In the custom view, I call draweeHolder.onAttach in constructor, and callsuper.setImageDrawable(mDraweeHolder.getTopLevelDrawable()); to display drawable, otherwise the Drawee won't appear at all.

oprisnik commented 7 years ago

If you're not using the original DraweeView, you can use the image pipeline directly: http://frescolib.org/docs/using-image-pipeline.html

usernotnull commented 6 years ago

@elyonsaber can you please share your custom view? I have a feeling I'm facing the same problem. I'm using SDV as a recyclerview decoration and the controller listener is not being fired up... (so the image isn't appearing)