2017-01-28 5 views
3

Это был мой первоначальный вопрос:Picasso + RxJava2: Метод вызова должно происходить от основного потока

Я пытаюсь показать несколько изображений в AutoScrollViewPager. Я использую Пикассо для достижения того же. Тем не менее, я хотел бы сделать то же самое с использованием 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) 

Любая помощь будет оценена по достоинству. :)

+0

Что делать, если вы удалите '.subscribeOn (Планировщики .newThread()) '? Ошибка говорит: «Вызов метода должен произойти из основного потока», но вы сообщаете вашему коду подписываться на новый поток. Или, может быть, '.subscribeOn (AndroidSchedulers.mainThread()), которые могут быть одинаковыми ... – JonesV

ответ

3

Вы загружаете изображение из потока исполнителей, которое 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.

Есть несколько вариантов для вас. Вы можете сделать всю работу instantiateItem в потоке пользовательского интерфейса, если вы проходите Looper.getMainLooper() в, или вы можете использовать метод RequestCreator.get() вместо RequestCreator.into(), или обернуть Picasso работы с:

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