【发布时间】:2020-04-23 08:33:26
【问题描述】:
我知道这个问题被问了很多时间,并且我知道通常情况下的答案,即arraylist.clear() 在拉动SwipeRefreshLayout 之前清除arraylist。但在我的情况下,它似乎有点不同,我完全不知道,所以让我一步一步告诉它。
我想做的事:
我有一个RecyclerView,它通常只显示一种类型的数据,即List<Post> posts。从这里开始,这工作得很好。现在,我想将来自 Google Admobs 的 NatvieAds 添加到 RecyclerView 的第一个元素中。
这是我的代码设置:
PostFragment:
public class PostFragment extends Fragment implement .....{
@Override
public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) {
initializeRecyclerView();
setUpSwipeRefreshLayout();
mSwipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
postAdapter.removeAllStuff(); //Here clear all the item in post
getPostInRoom(roomId);
}
});
}
private void initializeRecyclerView() {
recyclerView = binding.postRecyclerView;
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(),RecyclerView.VERTICAL,false));
postAdapter = new PostAdapter(this);
recyclerView.setAdapter(postAdapter);
}
private SwipeRefreshLayout mSwipeRefreshLayout;
private void setUpSwipeRefreshLayout() {
mSwipeRefreshLayout = binding.swipeRefreshLayout;
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mSwipeRefreshLayout.setRefreshing(true);
postAdapter.removeAllStuff(); //Here clear all the item in post
getPostInRoom(roomId);
}
});
}
// I calling my own API in ViewModel and observe the LiveData returned.
private void getPostInRoom(String roomId) {
viewModel.getAllPostInRoom(roomId).observe(getViewLifecycleOwner(), new Observer<List<Post>>() {
@Override
public void onChanged(List<Post> posts) {
mSwipeRefreshLayout.setRefreshing(false);
if(posts != null && posts.size() > 0){
binding.postRecyclerView.setVisibility(View.VISIBLE);
binding.emptyStateContainer.setVisibility(View.GONE);
binding.unblockRoomButton.setVisibility(View.GONE);
postAdapter.addAllPostToList(posts); // Here add all the arraylist item into the list in adapter
getNativeAdsFromAdmobForPostFragment(); // here called for Admobs
}else if(Objects.requireNonNull(posts).size() == 0){
binding.emptyStateContainer.setVisibility(View.VISIBLE);
binding.postRecyclerView.setVisibility(View.GONE);
}
}
});
}
如您所见,在SwipeRefreshLayout 中调用getPostInRoom() 之前,我已经调用了postAdapter.removeAllStuff()(为此我将附上下面的代码)。所以如果我没记错的话,arraylist应该是清楚的。
这是PostFragment 中用于调用 Admob 进行广告的代码
//HERE CALLED TO GOOGLE ADMOB FOR THE ADS
private AdLoader adLoader;
public void getNativeAdsFromAdmobForPostFragment(){
NativeAdOptions adOptions = new NativeAdOptions.Builder()
.setAdChoicesPlacement(ADCHOICES_TOP_RIGHT)
.build();
adLoader = new AdLoader.Builder(getActivity(), getResources().getString(R.string.admob_test_ad))
.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
@Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
// Show the ad.
if(!adLoader.isLoading()){
postAdapter.addAdsToList(unifiedNativeAd); //here update the ads into the arraylist of the recyclerView
}
}
})
.withAdListener(new AdListener() {
@Override
public void onAdFailedToLoad(int errorCode) {
// Handle the failure by logging, altering the UI, and so on.
Log.e("MainActivity", "The previous native ad failed to load. Attempting to"
+ " load another.");
if (!adLoader.isLoading()) {
}
}
})
.withNativeAdOptions(adOptions)
.build();
adLoader.loadAd(new AdRequest.Builder().build());
}
}
PostAdapter.java
public class PostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int UNIFIED_ADS_VIEW = 1;
private static final int POST_ITEM_VIEW = 2;
private List<Object> mRecyclerViewItem = new ArrayList<>();
public PostAdapter(PostAdapterListener listener) {
this.listener = listener;
}
public void addAllPostToList(List<Post> posts){
mRecyclerViewItem.addAll(posts); // Here add all the post into the mRecyclerViewItem
notifyDataSetChanged();
}
public void addAdsToList(UnifiedNativeAd unifiedNativeAd){
mRecyclerViewItem.add(0,unifiedNativeAd); // Here add the 1 nativeAds into the arrayList
notifyDataSetChanged();
}
public void removeAllStuff(){
mRecyclerViewItem.clear(); // Here already called before `getPostInRoom()` in SwipeFreshLayout
notifyDataSetChanged();
}
@Override
public int getItemViewType (int position) {
Object recyclerViewItem = mRecyclerViewItem.get(position);
if (recyclerViewItem instanceof UnifiedNativeAd) {
return UNIFIED_ADS_VIEW;
}
return POST_ITEM_VIEW;
}
@Override
public int getItemCount() {
return mRecyclerViewItem.size();
}
... all other code
}
我现在拥有的:
在上面的所有代码之后,
-
第一次加载
PostFragment时:行为是正确的,这意味着广告出现在recyclerView的第一项上,然后是我从服务器获取的post。 当我拉
SwipeRefreshLayout时:相同的post(这是3个帖子)重复并且RecyclerView中出现一个新广告,每次我拉SwipeRefreshLayout时,另外3个相同的帖子并且 1 个新广告再次插入到RecyclerView。
这意味着,PostAdapater 中的 mRecyclerViewItem 永远不会是 clear(),但是新项目会不断添加到 ArrayList 中,尽管我在获取新项目之前已经 clear()。
问题:
在上述情况下我做错了什么?
在 1 个 RecyclerView 中处理 2 种类型的
data(Post和UnifiedNativeAd)或 2 个数组列表的正确方法是什么?
【问题讨论】:
标签: android android-recyclerview admob android-livedata swiperefreshlayout