与admob广告的无尽回收视图

时间:2017-08-07 12:10:07

标签: android android-recyclerview

我正在尝试开发一个实现无限滚动Recyclerview的应用程序,当recyclerview到达底部时,它会加载50个项目,并且每10个项目之间放置一个admob原生广告。问题是滚动,我得到空指针异常。我试图弄清楚在活动类的onscroll方法上添加新项目的逻辑。这是异常的图像

enter image description here

以及活动和适配器类的代码。

活动类:

// A Native Express ad is placed in every nth position in the RecyclerView.
public static final int ITEMS_PER_AD = 10;

// The Native Express ad height.
private static final int NATIVE_EXPRESS_AD_HEIGHT = 150;

// The Native Express ad unit ID.
private static final String AD_UNIT_ID = "ca-app-pub-3940256099942544/1072772517";

// The RecyclerView that holds and displays Native Express ads and menu items.
private RecyclerView mRecyclerView;

// List of Native Express ads and MenuItems that populate the RecyclerView.
private List<Object> mRecyclerViewItems = new ArrayList<>();
private int loadCount;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_recyclerview_with_ads);

    mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);

    // Use this setting to improve performance if you know that changes
    // in content do not change the layout size of the RecyclerView.
    mRecyclerView.setHasFixedSize(true);

    // Specify a linear layout manager.
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
    mRecyclerView.setLayoutManager(layoutManager);

    generateData();

    // Update the RecyclerView item's list with menu items and Native Express ads.
    addNativeExpressAds();
    setUpAndLoadNativeExpressAds();

    // Specify an adapter.
    final RecyclerViewAdapter adapter = new RecyclerViewAdapter(RecyclerviewWithAds.this, mRecyclerViewItems, mRecyclerView);
    mRecyclerView.setAdapter(adapter);
    adapter.setOnLoadMoreListener(new OnLoadMoreListener() {
        @Override
        public void onLoadMore() {

            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {

                    //load data
                    //cant figure out the logic here.
                    Log.e("loadcount", "" + (loadCount + 1));
                    loadCount++;
                    Log.e("itemsList", "" + mRecyclerViewItems.size());

                    final int index = mRecyclerViewItems.size() - ((6 * loadCount) - (loadCount - 1));

                    Log.e("Modulus", "" + (mRecyclerViewItems.size() % ITEMS_PER_AD));
                    Log.e("index", "" + index);
                    final int end = index + 50;

                    for (int i = index; i <= end; i++) {
                        mRecyclerViewItems.add(new MenuItem("name " + i));
                    }
                    for (int i = (index + (ITEMS_PER_AD - (loadCount - 1))); i <= end; i += ITEMS_PER_AD) {
                        final NativeExpressAdView adView = new NativeExpressAdView(RecyclerviewWithAds.this);
                        Log.e("ads position", "" + i);
                        mRecyclerViewItems.add(i, adView);
                    }


                    mRecyclerView.post(new Runnable() {
                        @Override
                        public void run() {
                            final float scale = RecyclerviewWithAds.this.getResources().getDisplayMetrics().density;
                            int i;
                            // Set the ad size and ad unit ID for each Native Express ad in the items list.
                            for (i = (index + (ITEMS_PER_AD - (loadCount -1))); i <= end; i += ITEMS_PER_AD) {
                                final NativeExpressAdView adView =
                                        (NativeExpressAdView) mRecyclerViewItems.get(i);
                                final CardView cardView = (CardView) findViewById(R.id.ad_card_view);
                                final int adWidth = cardView.getWidth() - cardView.getPaddingLeft()
                                        - cardView.getPaddingRight();
                                AdSize adSize = new AdSize((int) (adWidth / scale), NATIVE_EXPRESS_AD_HEIGHT);
                                adView.setAdSize(adSize);
                                adView.setAdUnitId(AD_UNIT_ID);
                            }

                            // Load the first Native Express ad in the items list.
                            loadNativeExpressAd(0);
                        }
                    });

                    adapter.notifyDataSetChanged();
                    adapter.setLoaded();
                }
            }, 1000);
        }
    });
}

/**
 * Adds Native Express ads to the items list.
 */
public void generateData() {


    for (int i = 0; i < 50; i++) {

        mRecyclerViewItems.add(new MenuItem("name " + i));

    }
}

private void addNativeExpressAds() {

    // Loop through the items array and place a new Native Express ad in every ith position in
    // the items List.
    for (int i = 0; i <= mRecyclerViewItems.size(); i += ITEMS_PER_AD) {
        final NativeExpressAdView adView = new NativeExpressAdView(RecyclerviewWithAds.this);
        mRecyclerViewItems.add(i, adView);
    }
}


/**
 * Sets up and loads the Native Express ads.
 */
private void setUpAndLoadNativeExpressAds() {
    // Use a Runnable to ensure that the RecyclerView has been laid out before setting the
    // ad size for the Native Express ad. This allows us to set the Native Express ad's
    // width to match the full width of the RecyclerView.
    mRecyclerView.post(new Runnable() {
        @Override
        public void run() {
            final float scale = RecyclerviewWithAds.this.getResources().getDisplayMetrics().density;
            // Set the ad size and ad unit ID for each Native Express ad in the items list.
            for (int i = 0; i <= mRecyclerViewItems.size(); i += ITEMS_PER_AD) {
                final NativeExpressAdView adView =
                        (NativeExpressAdView) mRecyclerViewItems.get(i);
                final CardView cardView = (CardView) findViewById(R.id.ad_card_view);
                final int adWidth = cardView.getWidth() - cardView.getPaddingLeft()
                        - cardView.getPaddingRight();
                AdSize adSize = new AdSize((int) (adWidth / scale), NATIVE_EXPRESS_AD_HEIGHT);
                adView.setAdSize(adSize);
                adView.setAdUnitId(AD_UNIT_ID);
            }

            // Load the first Native Express ad in the items list.
            loadNativeExpressAd(0);
        }
    });
}

/**
 * Loads the Native Express ads in the items list.
 */
private void loadNativeExpressAd(final int index) {

    if (index >= mRecyclerViewItems.size()) {
        return;
    }

    Object item = mRecyclerViewItems.get(index);
    if (!(item instanceof NativeExpressAdView)) {
        throw new ClassCastException("Expected item at index " + index + " to be a Native"
                + " Express ad.");
    }

    final NativeExpressAdView adView = (NativeExpressAdView) item;

    // Set an AdListener on the NativeExpressAdView to wait for the previous Native Express ad
    // to finish loading before loading the next ad in the items list.
    adView.setAdListener(new AdListener() {
        @Override
        public void onAdLoaded() {
            super.onAdLoaded();
            // The previous Native Express ad loaded successfully, call this method again to
            // load the next ad in the items list.
            loadNativeExpressAd(index + ITEMS_PER_AD);
        }

        @Override
        public void onAdFailedToLoad(int errorCode) {
            // The previous Native Express ad failed to load. Call this method again to load
            // the next ad in the items list.
            Log.e("MainActivity", "The previous Native Express ad failed to load. Attempting to"
                    + " load the next Native Express ad in the items list.");
            loadNativeExpressAd(index + ITEMS_PER_AD);
        }
    });

    // Load the Native Express ad.
    adView.loadAd(new AdRequest.Builder().build());
}

适配器类:

// A menu item view type.
private static final int MENU_ITEM_VIEW_TYPE = 0;

// The Native Express ad view type.
private static final int NATIVE_EXPRESS_AD_VIEW_TYPE = 1;

// An Activity's Context.
private final Context mContext;

// The list of Native Express ads and menu items.
private final List<Object> mRecyclerViewItems;


private int visibleThreshold = 5;
private int lastVisibleItem, totalItemCount;
private boolean isLoading;

private OnLoadMoreListener mOnLoadMoreListener;

/**
 * For this example app, the recyclerViewItems list contains only
 * {@link MenuItem} and {@link NativeExpressAdView} types.
 */
public RecyclerViewAdapter(Context context, List<Object> recyclerViewItems,RecyclerView mRecyclerView) {
    this.mContext = context;
    this.mRecyclerViewItems = recyclerViewItems;

    final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            if (dy > 0) {
                totalItemCount = linearLayoutManager.getItemCount();
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                    if (mOnLoadMoreListener != null) {
                        mOnLoadMoreListener.onLoadMore();
                    }
                    isLoading = true;
                }
            }

        }
    });
}

/**
 * The {@link MenuItemViewHolder} class.
 * Provides a reference to each view in the menu item view.
 */
public class MenuItemViewHolder extends RecyclerView.ViewHolder {
    private TextView menuItemName;
    private TextView menuItemDescription;
    private TextView menuItemPrice;
    private TextView menuItemCategory;
    private ImageView menuItemImage;

    MenuItemViewHolder(View view) {
        super(view);
        menuItemImage = (ImageView) view.findViewById(R.id.menu_item_image);
        menuItemName = (TextView) view.findViewById(R.id.menu_item_name);
        menuItemPrice = (TextView) view.findViewById(R.id.menu_item_price);
        menuItemCategory = (TextView) view.findViewById(R.id.menu_item_category);
        menuItemDescription = (TextView) view.findViewById(R.id.menu_item_description);
    }
}

/**
 * The {@link NativeExpressAdViewHolder} class.
 */
public class NativeExpressAdViewHolder extends RecyclerView.ViewHolder {

    NativeExpressAdViewHolder(View view) {
        super(view);
    }
}

@Override
public int getItemCount() {
    return mRecyclerViewItems.size();
}

/**
 * Determines the view type for the given position.
 */
@Override
public int getItemViewType(int position) {
    return (position % RecyclerviewWithAds.ITEMS_PER_AD == 0) ? NATIVE_EXPRESS_AD_VIEW_TYPE
            : MENU_ITEM_VIEW_TYPE;
}

/**
 * Creates a new view for a menu item view or a Native Express ad view
 * based on the viewType. This method is invoked by the layout manager.
 */
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    switch (viewType) {
        case MENU_ITEM_VIEW_TYPE:
            View menuItemLayoutView = LayoutInflater.from(viewGroup.getContext()).inflate(
                    R.layout.menu_item_container, viewGroup, false);
            return new MenuItemViewHolder(menuItemLayoutView);
        case NATIVE_EXPRESS_AD_VIEW_TYPE:
            // fall through
        default:
            View nativeExpressLayoutView = LayoutInflater.from(
                    viewGroup.getContext()).inflate(R.layout.native_express_ad_container,
                    viewGroup, false);
            return new NativeExpressAdViewHolder(nativeExpressLayoutView);
    }

}

/**
 *  Replaces the content in the views that make up the menu item view and the
 *  Native Express ad view. This method is invoked by the layout manager.
 */
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    int viewType = getItemViewType(position);
    switch (viewType) {
        case MENU_ITEM_VIEW_TYPE:
            MenuItemViewHolder menuItemHolder = (MenuItemViewHolder) holder;
            MenuItem menuItem = (MenuItem) mRecyclerViewItems.get(position);

            // Get the menu item image resource ID.

            // Add the menu item details to the menu item view.
            menuItemHolder.menuItemName.setText(menuItem.getName());
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(mContext, "position : "+ position , Toast.LENGTH_SHORT).show();
                }
            });
            break;
        case NATIVE_EXPRESS_AD_VIEW_TYPE:
            // fall through
        default:
            NativeExpressAdViewHolder nativeExpressHolder =
                    (NativeExpressAdViewHolder) holder;
            NativeExpressAdView adView =
                    (NativeExpressAdView) mRecyclerViewItems.get(position);
            ViewGroup adCardView = (ViewGroup) nativeExpressHolder.itemView;
            // The NativeExpressAdViewHolder recycled by the RecyclerView may be a different
            // instance than the one used previously for this position. Clear the
            // NativeExpressAdViewHolder of any subviews in case it has a different
            // AdView associated with it, and make sure the AdView for this position doesn't
            // already have a parent of a different recycled NativeExpressAdViewHolder.
            if (adCardView.getChildCount() > 0) {
                adCardView.removeAllViews();
            }
            if (adView.getParent() != null) {
                ((ViewGroup) adView.getParent()).removeView(adView);
            }

            // Add the Native Express ad to the native express ad view.
            adCardView.addView(adView);
    }
}

//Extra methods
public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
    this.mOnLoadMoreListener = mOnLoadMoreListener;
}


public void setLoaded() {
    isLoading = false;
}

如果有人帮我有效地实施这一点,我将非常感激。

0 个答案:

没有答案