首页 > 解决方案 > Android:如何使用毕加索和目标为多个图像添加水印

问题描述

我有一个从服务器下载图像的应用程序,添加水印,然后允许用户通过其他应用程序共享它们。我使用毕加索将图像加载到目标中。

问题是将图像加载到目标中需要一些时间,所以我需要找到一种方法来等待该过程完成。我读过关于 CompletableFuture 的文章,但它只针对 Android +24,这是不可接受的。

这是我到目前为止所做的

//Global var
final List<Target> remoteImgTargets = new ArrayList<>();

//method
List<ImageToShare> remoteImages = new ArrayList<>();
final ArrayList<Uri> finishedImages = new ArrayList<>();

int countImages = remoteImages.size();
for (int i = 0; i < countImages; i++) {
            final int k=i;
            Target target = new Target() {

                @Override
                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {

                    remoteImgTargets.remove(this);

                    //Add watermark here
                    finishedImages.add(Utils.getLocalBitmapUri(watermakedBmp, context));
                    Log.e("Targets", "Loaded: " + k);
                }

                @Override
                public void onBitmapFailed(Drawable errorDrawable) {
                    remoteImgTargets.remove(this);
                    Log.e("Targets", "onBitmapFailed(): ");
                }

                @Override
                public void onPrepareLoad(Drawable placeHolderDrawable) {
                    Log.e("Targets", "Preparing: " + k);
                }
            };
            remoteImgTargets.add(target);
            Picasso.with(context)
                    .load(remoteImages.get(k).getImageurl()) // Start loading the current target
                    .into(target);

        }

进一步我使用 RxAndroid 来观察进程并处理

ArrayList<Uri> globalUriArray = new ArrayList<>();
Observable<Uri> observable2 = Observable
                .fromIterable(finishedImages)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());

        Observer<Uri> observer = new Observer<Uri>() {
            @Override
            public void onSubscribe(Disposable d) {
                //TODO
            }

            @Override
            public void onNext(Uri uri) {
                globalUriArray.add(uri);
            }

            @Override
            public void onError(Throwable e) {
                //TODO
            }

            @Override
            public void onComplete() {
                if(globalUriArray.size()>0) {
                    //Display share intent
                }
            }
        };

        observable2.subscribe(observer);

*问题 * 目标加载被遗忘,只有一小部分图像被加载。

需要帮助 如何等待毕加索目标完成加载,如果可能的话,可能会触发回调或其他任何事情。

提前致谢...

标签: androidarraylistpicassorx-androidtarget

解决方案


这里的问题是,您没有同步所有内容,我的意思是您在单独的线程上加载图像并添加水印,最后在调度程序线程上调用所有这些 Rx,并且图像的加载发生在完全不同的主线程上,

因此,您必须同步所有获取图像并在调度程序线程上添加水印并将图像加载到主线程,找到下面的示例。我已经把它变成了通用的,以给出一个应该如何完成的想法。

 private void loadImageObserver(final String url) {
        Observable.create(new ObservableOnSubscribe<Bitmap>() {
            @Override
            public void subscribe(final ObservableEmitter<Bitmap> emitter) {
                //Use any-way to download bitmap from url
                //here Picasso is used to download the bitmap as was the question 

                try {
                    Bitmap bitmap = Picasso.get()
                            .load(url) // Start loading the current target
                            .get();
                    if (bitmap != null) {
                        emitter.onNext(bitmap);
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                    emitter.onError(e);
                }


            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Bitmap>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d(TAG, "subscribed");
                    }

                    @Override
                    public void onNext(Bitmap bitmap) {
                        Log.d(TAG, "on next " + bitmap.getWidth() + " " + bitmap.getHeight() + " " + bitmap.getByteCount());
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "error " + e.getLocalizedMessage());
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "on complete");
                    }
                });
    }

推荐阅读