Подтвердить что ты не робот

Picasso не может загружать изображение внутри метода StorageReference onSuccess

При попытке Picasso во время выполнения onStart() он обычно загружает изображение из Firebase, используя ссылку загрузки с консоли.

Но когда я пытаюсь загрузить изображение внутри метода StorageReference onSuccess, он просто не будет работать.

Этот класс расширяет фрагмент:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == GALLERY_IN && resultCode == Activity.RESULT_OK) {
        isGranted = true;
        String path = FireStorage.retUID() + "/";
        showIndProgress();
        Uri uri = data.getData();

        StorageReference childPathRef = FireStorage.storageRef.child(path + uri.getLastPathSegment());
        childPathRef.putFile(uri)
                .addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
                        if(task.isSuccessful()) {
                            Picasso.with(mContext).load(task.getResult().getDownloadUrl())
                                    .into(profView);

                            Picasso.Builder build = new Picasso.Builder(mContext);
                            build.listener(new Picasso.Listener() {
                                @Override
                                public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
                                    Toast.makeText(mContext, "exception\n" + exception.toString(), Toast.LENGTH_SHORT).show();

                                }
                            });
                            progressDialog.dismiss();
                        } else {
                            //failed
                        }

                    }
                });

    }

}

Это мой экземпляр FirebaseStorage в другом классе:

public static FirebaseStorage storage = FirebaseStorage.getInstance();
public static StorageReference storageRef = 
                           storage.getReferenceFromUrl("gs://myurl.appspot.com/");

манифеста:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Мой XML-макет:

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="@drawable/gcover"
    android:id="@+id/relativeLayout">

    <de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/profPhoto"
        android:clickable="true"
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:padding="20dp"
        android:src="@drawable/default_prof"
        android:scaleType="centerCrop"
        app:civ_border_color="@color/trans"
        app:civ_border_width="2dp"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

Моя инициализация просмотров:

@Override
public View onCreateView(LayoutInflater inflater,
                         ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_prof, container, false);
    profView = (CircleImageView) view.findViewById(R.id.profPhoto);

    btn1 = (Button) view.findViewById(R.id.btn_1);
    btn2 = (Button) view.findViewById(R.id.btn_2);
    btn3 = (Button) view.findViewById(R.id.btn_3);
    return view;
}
4b9b3361

Ответ 1

Я просто переключился с CircleImageView на обычный ImageView, и он внезапно сработал.

Ответ 2

Обновление 2:

Пока код, который я опубликовал, работает для меня, вы указываете, что он не подходит для вас. В моем тесте не используется фрагмент, я не знаю, какую версию библиотек вы используете, теперь он знает, как добавляется фрагмент в макет и т.д. Существует слишком много возможных причин для эффективного отладки это на SO.

В качестве эксперимента вы можете попробовать использовать Glide и FirebaseUI для загрузки вместо Picasso. Код показан ниже и работает для меня. Поскольку загрузка осуществляется из ссылки на хранилище, а не URL-адреса, для этого подхода требуется доступ для чтения к хранилищу. Вам также нужно добавить эти строки в зависимости от сборки:

// FirebaseUI 2.0.1 is the version to use for Firebase SDK version 11.0.1
// SDK/Firebase version compatibility is important.
// See the FirebaseUI docs for a table of compatible versions.
compile 'com.firebaseui:firebase-ui-storage:2.0.1'
compile 'com.github.bumptech.glide:glide:3.8.0'

.

childPathRef.putFile(Uri.fromFile(file))
    .addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
            if (task.isSuccessful()) {
                Log.d(TAG, "Upload: SUCCESS");

                Glide.with(mContext)
                    .using(new FirebaseImageLoader())
                    .load(childPathRef)
                    .dontAnimate()
                    .listener(new RequestListener<StorageReference, GlideDrawable>() {
                        @Override
                        public boolean onException(Exception e, StorageReference model,
                               Target<GlideDrawable> target, boolean isFirstResource) {
                            Log.e(TAG, "Download: FAILED: ", e);
                            return false;
                        }
                        @Override
                        public boolean onResourceReady(GlideDrawable resource,
                               StorageReference model, Target<GlideDrawable> target,
                               boolean isFromMemoryCache, boolean isFirstResource) {
                            Log.d(TAG, "Download: SUCCESS");
                            return false;
                        }
                    })
                    .into(mCircleImageView);
            } else {
                Log.e(TAG, "Upload: FAILED: " + task.getException().getMessage());
            }
        }
    });

Update:

Дополнительная отладка показала, что загрузка и загрузка были успешно завершены. Проблема заключалась в рендеринге загруженного изображения. Документация для CircleImageView указывает, что noFade() необходимо использовать при загрузке из Picasso:

Если вы используете библиотеку загрузки изображений, такую ​​как Picasso или Glide, вам нужно отключите их анимацию затухания, чтобы избежать перепутанных изображений. Для Пикассо используйте опцию noFade(), для использования Glide dontAnimate().

Было также обнаружено, что маленькие изображения были визуализированы, но большие изображения были отображены как черные. fit() был добавлен, чтобы заставить Picasso изменить размер изображения.


Чтобы обнаружить успех и неудачу при загрузке, используйте прослушиватель завершения, а не только прослушиватель успеха, и протестируйте task.isSuccessful(). Загрузка, вероятно, не выполняется из-за правил безопасности или недействительна StorageReference:

StorageReference childPathRef = Class.storageRef.child(path + uri.getLastPathSegment());
childPathRef.putFile(uri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
        if (task.isSuccessful()) {
            Log.d(TAG, "Upload: SUCCESS");
            Picasso.with(mContext)
                .load(task.getResult().getDownloadUrl())
                .noFade()
                .fit()
                .into(profView, new Callback() {
                    @Override
                    public void onSuccess() {
                        Log.d(TAG, "Download: SUCCESS");
                        Toast.makeText(mContext, "download done" , Toast.LENGTH_SHORT).show();                        }

                    @Override
                    public void onError() {
                        Log.d(TAG, "Download: FAILED");
                    }
                });
            Toast.makeText(mContext, "upload done" , Toast.LENGTH_SHORT).show();
        } else {
            Log.e(TAG, "Upload: FAILED: " + task.getException().getMessage());
        }
        progressDialog.dismiss();
    }
});

Ответ 3

Ограничения для de.hdodenhof.circleimageview.CircleImageView

  • ScaleType всегда CENTER_CROP, и вы получите исключение, если попытаетесь его изменить. Это (в настоящее время) по дизайну, поскольку оно идеально подходит для изображений профиля.
  • Включение функции adjustViewBounds не поддерживается, так как для этого требуется неподдерживаемый тип ScaleType
  • Если вы используете библиотеку для загрузки изображений, такую ​​как Picasso или Glide, вам необходимо отключить их анимацию затухания, чтобы избежать перепутанных изображений. Для Picasso используйте параметр noFade(), для использования Glide dontAnimate(). Если вы хотите сохранить анимацию fadeIn, вам нужно получить изображение в Target и применить собственную анимацию самостоятельно при получении растрового изображения.
  • Использование TransitionDrawable с CircleImageView не работает должным образом и приводит к испорченным изображениям.

Ответ 4

Возможно, что в этой строке кода:

     Picasso.with(mContext).load(task.getResult().getDownloadUrl())
                                .into(profView);    

profView воссоздает с фрагментом, а Picasso.into(View view) сохраняет ссылку недели для просмотра.

Из документов:

public void into (android.widget.ImageView target) Асинхронно выполняет запрос в указанный ImageView. Примечание. Этот метод сохраняет слабую ссылку на экземпляр ImageView и будет автоматически поддерживают рециркуляцию объектов.

Попробуйте использовать:

public void into(@NotNull ImageView target,
             Callback callback)

Ответ 5

Возможно, это конфликт с CircleImageView.

Попробуйте изменить его с помощью ImageView или определите CircleImageView как ImageView.

Попробуйте:

ImageView profView = (ImageView) view.findViewById(R.id.profPhoto);