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 - 从函数内启用 Android 应用程序按钮

java - 在 Appium Java 客户端中按下主页按钮

Java:获取与枚举关联的对象

javascript - React Native Expo 未捕获错误 'this.props=t'

Android Picasso - 从网络下载视频缩略图

java - 接口(interface)中的变量/构造函数

java - 如何使用 JDialog 类删除或隐藏父窗口

java - JUnit - 静态类是否维护测试类之间的状态?

java - 带位图的高效onDraw和硬件加速的复杂裁剪