2016-09-20 1 views
-1

В основном я использую MVP с RxJava в моем проекте, но в связи с отсутствием в Rx версии Youtube API я не использовал мой MVP подход.Progressbar быстро удаляется из endlessrecycleview

В настоящее время я пытаюсь сделать классическую реализацию (используя thread's) endlessrecycleview, который отображает видео YouTube.

Проблема с моим нынешним подходом заключается в том, что я не могу понять, почему ProgressBar быстро скрывается от endlessrecyleview.

private void setupRecyclerView() { 
    mYoutubeVideoRecyclerView.setAdapter(adapter); 
    mYoutubeVideoRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); 
    mYoutubeVideoRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { 
     @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 
     super.onScrolled(recyclerView, dx, dy); 
     if (true && !(hasFooter())) { 
      LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); 
      //position starts at 0 
      if (layoutManager.findLastCompletelyVisibleItemPosition() 
       == layoutManager.getItemCount() - 2) { 
      Log.d(TAG, "ProgressBar - item INSERTED At index = " + adapter.getItemCount()); 
      adapter.getVideos().add(null); 
      recyclerView.getAdapter().notifyItemInserted(adapter.getItemCount() - 1); 

      // TODO: 9/20/16 the bellow 2 lines make the progressbar not being displayed 
      getYoutubeVideos(); 
      displayDataOrShowMessage(); 
      } 
     } 
     } 
    }); 
    } 

...

private void getYoutubeVideos() { 
    Thread thread = new Thread(new Runnable() { 
     @Override public void run() { 
     try { 
      videoEntries = videoPresenter.getYoutubeVideoList(getActivity()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     } 
    }); 
    thread.start(); 
    try { 
     thread.join(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    } 

...

private void displayDataOrShowMessage() { 
    if (videoEntries != null) { 
     showVideos(videoEntries); 
     showSelectedVideo((videoEntries.get(0)).getVideoId()); 
    } else { 
     showMessage(R.string.probleme_connection); 
     ((VideoPlayerFragment) (getActivity()).getFragmentManager().findFragmentByTag("video_player")) 
      .pause(); 
    } 
    } 

...

public void showVideos(List<VideoEntry> videos) { 
    Log.d(TAG, "ProgressBar - Adapter data size before adding items = " + adapter.getItemCount()); 
    try { 
     int size = adapter.getItemCount(); 
     Log.d(TAG, "ProgressBar - item REMOVED from index = " + adapter.getItemCount()); 
     adapter.getVideos().remove(size - 1);//removes footer 
     adapter.addVideos(videos); 
     adapter.notifyItemRangeChanged(size - 1, adapter.getItemCount() - size); 
    } catch (ArrayIndexOutOfBoundsException e) { 
     adapter.addVideos(videos); 
     adapter.notifyDataSetChanged(); 
    } 
    Log.d(TAG, "ProgressBar - Adapter data size after adding items = " + adapter.getItemCount()); 

    mYoutubeVideoRecyclerView.requestFocus(); 
    progressBar.setVisibility(View.INVISIBLE); 
    infoTextView.setVisibility(View.INVISIBLE); 
    mYoutubeVideoRecyclerView.setVisibility(View.VISIBLE); 
    Log.d(TAG, "showVideos -- data is set to list"); 
    } 

ответ

1

Это не работает, потому что вы начинаете новую нить и делает поток пользовательского интерфейса ожидает, когда он закончит, когда вы вызовете join().

Вы по существу блокируете поток пользовательского интерфейса, поэтому adapter.getVideos().add(null); и adapter.getVideos().remove(size - 1); вызываются сразу один за другим, и он никогда не получает должным образом рисования на экране.

то, что вам нужно сделать, это разрешить этому потоку бежать, НЕ ОДИНАТЬ join() и передать videos обратно в поток пользовательского интерфейса, а затем добавить их в адаптер. Но, конечно, это легче сказать, чем сделать.

Один «простой» способ - использовать AsyncTask (https://developer.android.com/reference/android/os/AsyncTask.html), но у них есть своя доля проблем с потенциальной утечкой памяти, если вы не знаете, что делаете.

Правильный подход заключается в том, чтобы данные от адаптера могли быть subscribed/unsusbribed и позволить фоновому потоку добавлять данные. Но это большой рефакторинг, а не объем ответа.

Я знаю, что это не полный ответ, но я надеюсь, что это указывает на направление.

Кроме того, я предлагаю использовать эту библиотеку https://github.com/eyeem/RecyclerViewTools (что я создал). Он полностью поддерживает верхние и нижние колонтитулы и EndlessScroll из коробки и должен сделать часть вашего кода проще.

0

Ok, Асинхронный ад, так что я сделал код рефакторинг использовать версию Rx:

public void getYoutubeVideoList(final Context context, Boolean isRefresh) { 
    MalitelApplication application = MalitelApplication.get(videoMvpView.getContext()); 
    MalitelService malitelService = application.getMalitelService(Constants.malitelYoutubeUrl); 
    subscription = application.getYoutubeConnector().getYoutubeVideosObservable(isRefresh) 
     .observeOn(AndroidSchedulers.mainThread()) 
     .subscribeOn(application.defaultSubscribeScheduler()) 
     .subscribe(new Observer<List<VideoEntry>>() { 
      @Override public void onCompleted() { 
      } 

      @Override public void onError(Throwable e) { 
      videoMvpView.showMessage(R.string.probleme_connection); 
      } 

      @Override public void onNext(List<VideoEntry> videos) { 
      videoMvpView.showVideos(videos); 
      videoMvpView.showSelectedVideo((videos.get(0)).getText()); 
      } 
     }); 
    } 

..

public Observable<List<VideoEntry>> getYoutubeVideosObservable(final Boolean isRefresh) { 
    return Observable.create(new Observable.OnSubscribe<List<VideoEntry>>() { 
     @Override public void call(Subscriber<? super List<VideoEntry>> subscriber) { 
     try { 
      search = 
       youtube.search().list("id,snippet").setChannelId(Constants.malitelYoutubeChannelId); 
      search.setKey(DeveloperKey.DEVELOPER_KEY); 
      search.setType("video"); 
      search.setMaxResults(NUMBER_OF_VIDEOS_RETURNED); 
      search.setFields(
       "items(id/videoId,snippet/title,snippet/description,snippet/thumbnails/default/url)," 
        + "nextPageToken,pageInfo,prevPageToken"); 

      if (!isRefresh) { 
      search.setPageToken(nextPageToken); 
      } else { 
      totalResults = 0; 
      } 
     } catch (IOException e) { 
      Log.d(TAG, "Could not initialize: " + e); 
     } 

     // Call the API and print results. 
     SearchListResponse searchResponse = null; 
     List<SearchResult> searchResultList = null; 
     try { 
      searchResponse = search.execute(); 

      if (searchResponse != null) { 
      searchResultList = searchResponse.getItems(); 
      nextPageToken = searchResponse.getNextPageToken(); 
      if (nextPageToken != null) Log.d(TAG, nextPageToken); 
      } 

      if (searchResultList != null) { 
      fillVideoEntry(searchResultList.iterator()); 
      } 

      if (mVideoEntries != null) { 
      totalResults += mVideoEntries.size(); 
      Log.d(TAG, "totalResults : " + totalResults); 
      } 

      if (!subscriber.isUnsubscribed()) { 
      subscriber.onNext(mVideoEntries); 
      subscriber.onCompleted(); 
      } 
     } catch (IOException e) { 
      if (!subscriber.isUnsubscribed()) { 
      subscriber.onError(e); 
      } 
     } 
     } 
    }); 
    } 
Смежные вопросы