java - picasso + RxJava2 : Method call should happen from the main thread

标签 java android picasso rx-java2

这是我最初的问题:

我试图在 AutoScrollViewPager 中显示一些图像。我正在使用 Picasso 来达到同样的目的。但是,我想使用 Rxjava2 + Picasso 来做同样的事情。我对这个 RxJava 概念有点陌生。因此,如果有人可以帮助我提供详细信息,将以下内容转换为 RxJava 代码,我将不胜感激。

这就是我在 onViewCreated()

中所做的
imageAdapter = new ImageAdapter(getActivity());
autoScrollViewPager.setAdapter(imageAdapter);
autoScrollViewPager.setCurrentItem(imageAdapter.getCount() - 1);
autoScrollViewPager.startAutoScroll();
autoScrollViewPager.setInterval(4000);

这是我的ImageAdapter

ImageAdapter(Context context){
    this.context=context;
    mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
    return GalImages.length;
}

@Override
public boolean isViewFromObject(View view, Object object) {
    return view == ((RelativeLayout) object);
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
    LayoutInflater inflater = (LayoutInflater) container.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.pager_item,null);
    ((ViewPager) container).addView(view);
    final ImageView img = (ImageView) view.findViewById(R.id.imageView);
    Picasso.with(context)
            .load(GalImages[position])
            .fit()
            .into(img);
    return view;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    container.removeView((RelativeLayout)object);
}

如何将其转换为 RxJava 代码?任何帮助将不胜感激。

这就是我尝试做的

我稍微更改了 ImageAdapter:

@Override
public Object instantiateItem(ViewGroup container, int position) {
    LayoutInflater inflater = (LayoutInflater) container.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.pager_item,null);
    ((ViewPager) container).addView(view);
    img = (ImageView) view.findViewById(R.id.imageView);
    loadImagesWithPicasso(position)
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe();
    return view;
}

public Completable loadImagesWithPicasso(int position) {
   return Completable.fromAction(new Action() {
       @Override
       public void run() throws Exception {
           Picasso.with(context)
                  .load(GalImages[position])
                  .fit()
                  .into(new Target() {
                            @Override
                            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {

                            }

                            @Override
                            public void onBitmapFailed(Drawable errorDrawable) {

                            }

                            @Override
                            public void onPrepareLoad(Drawable placeHolderDrawable) {
                                img.setImageDrawable(placeHolderDrawable);
                            }
                        });
       }
   });
}

但不幸的是,这没有用,我最终遇到了这个错误:

java.lang.IllegalStateException: Method call should happen from the main thread.
at com.squareup.picasso.Utils.checkMain(Utils.java:136)
at com.squareup.picasso.RequestCreator.into(RequestCreator.java:496)
at com.kaaddevelopers.myprescriptor.ImageAdapter$1.run(ImageAdapter.java:79)
at io.reactivex.internal.operators.completable.CompletableFromAction.subscribeActual(CompletableFromAction.java:34)
at io.reactivex.Completable.subscribe(Completable.java:1613)
at io.reactivex.internal.operators.completable.CompletableSubscribeOn$SubscribeOnObserver.run(CompletableSubscribeOn.java:64)
at io.reactivex.Scheduler$1.run(Scheduler.java:134)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)

任何帮助将不胜感激。 :)

最佳答案

您正在从执行线程加载图像,这是 Picasso 不允许的(如果您问我,这是一个很好的选择,有更好的方法来处理同步问题,但现在就是这样)。

可以看到这个决定的详细信息in this thread :

It was a mistake from Picasso to allow external callers to invoke into() other than the main thread. Those methods deal with view recycling and canceling without synchronization, hence in Picasso 2.3 we added the checks.

您有多种选择。您可以在 UI 线程中完成整个 instantiateItem 工作,如果您将 Looper.getMainLooper() 传入,或者您可以使用 RequestCreator.get() 方法而不是 RequestCreator.into(),或者包装你的 Picasso 工作:

context.runOnUiThread(new Runnable() {
    @Override
    public void run() {
         // Can call RequestCreator.into here
    }
});

关于java - picasso + RxJava2 : Method call should happen from the main thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41908613/

相关文章:

java - 初级 Java 程序员的挣扎(未找到行)

android - 在以下位置找不到带有哈希字符串 'android-25'的目标:/home/hisham/Android/Sdk

android - picasso 没有加载图像

android - 设置最大宽度以使用 Picasso 加载图像

android - picasso 图像未在自定义信息窗口中加载为什么?

java - 根据移动和桌面浏览器切换布局

java - 为什么FrameLength为-1?

java - 从 Java 中的字符串中删除模式

Android浏览器自动下载图片

java - 读取 GoogleSignIn 的 awsconfiguration.json 时出错