基本上我在我的项目中使用 MVP 和 RxJava ,但由于缺少Rx版本的 Youtube API ,我没有使用我的MVP方法。
目前,我正在尝试制作显示YouTube视频的endlessrecycleview
经典实现(使用主题)。
我当前的方法存在的问题是,我无法弄清楚为什么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");
}
答案 0 :(得分:1)
它不起作用,因为你启动一个新线程并让你的UI线程在你调用join()
时等待它完成。
你基本上阻止了UI线程,因此adapter.getVideos().add(null);
和adapter.getVideos().remove(size - 1);
会立即被一个接一个地调用,并且它永远不会在屏幕上正确绘制。
你要做的是让该线程自由运行,不要join()
它并将videos
传递回UI线程然后将它们添加到适配器。但当然说起来容易做起来难。
One&#34; easy&#34;方法是使用AsyncTask
(https://developer.android.com/reference/android/os/AsyncTask.html),但如果您不知道自己在做什么,那么它们可能会分担潜在的内存泄漏问题。< / p>
正确的方法是让来自适配器的数据可以是subscribed/unsusbribed
并让后台线程添加数据。但这是一个更大的重构,而不是答案的范围。
我知道这不是一个完整的答案,但我希望它能指出你的方向。
另外,我建议使用这个库https://github.com/eyeem/RecyclerViewTools(我创建的)。它完全支持heades / footers和EndlessScroll开箱即用,并且可以使你的一些代码变得更容易。
答案 1 :(得分:0)
好的,Async是地狱,所以我做了一个代码重构来使用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);
}
}
}
});
}