由于Admob广告,Recyclerview在滚动时出现延迟

13

我想在RecyclerView中加载广告,广告已经成功加载,但是滚动时会导致很多卡顿。

以下是我在Adapter的OnBindViewHolder方法中编写的代码。

如何解决这个问题?

((DealHolder) holder).adcardView.post(new Runnable() {
                @Override
                public void run() {
                    final NativeExpressAdView adView = new NativeExpressAdView(((DealHolder) holder).itemView.getContext());
                    final int adWidth = ((DealHolder) holder).adcardView.getWidth() - ((DealHolder) holder).adcardView.getPaddingLeft()
                            - ((DealHolder) holder).adcardView.getPaddingRight();
                    final int adHeight = ((DealHolder) holder).adcardView.getHeight() - ((DealHolder) holder).adcardView.getPaddingBottom()
                            - ((DealHolder) holder).adcardView.getPaddingTop();
                    final float scale = ((DealHolder) holder).adcardView.getResources().getDisplayMetrics().density;
                    AdSize adSize = new AdSize((int) (adWidth / scale), (int) (adHeight / scale));
                    adView.setAdSize(adSize);
                    adView.setAdUnitId(((DealHolder) holder).adcardView.getContext().getString(R.string.test_adunit_id));
                    AdRequest request = new AdRequest.Builder().addTestDevice("jjhjhbjhjhjhjhjhjhjh").build();
                    adView.loadAd(request);
                    adView.setAdListener(new AdListener() {
                        @Override
                        public void onAdLoaded() {
                            super.onAdLoaded();
                        }

                        @Override
                        public void onAdFailedToLoad(int i) {
                            super.onAdFailedToLoad(i);
                        }
                    });
                    ((DealHolder) holder).adcardView.removeAllViews();
                    ((DealHolder) holder).adcardView.addView(adView);
                }
            });

使用systrace来了解你浪费时间的具体操作。 - azizbekian
另一个建议。每次使用时都在进行强制转换。只需进行一次转换并将其保存在DealHolder变量中。 - Efe AYDIN
2个回答

10

改进:

  1. 在用户尝试滚动时不要尝试加载您的Adview。为此,使您的适配器recylerView具有滚动意识,然后检查scroll_state==RecylerView.Scroll_IDLE,然后才加载您的AdView。

  2. 如果所有的AdView都具有相同的宽度和高度,请不要每次用户滚动时都进行计算,将其缓存在一个变量中。

  3. 请勿动态添加和删除NativeExpressAdView,而是在您的item_view中使用XML版本。您可以基于条件隐藏和显示。在XML视图中设置所有可能需要的属性。


1
我正在使用 CardView,并且如果我使用 XML 版本,则不会显示广告。仅通过计算 left right padding 动态工作。版本为 1.3。 - amodkanthe
@apk 我会尽力想出一个。 - krishan

1
为每个视图持有者创建一个新的AdView会消耗大量资源。
不要在每个视图持有者上创建新的adview,而是在一定间隔后充气adview,例如每5或10个项目后。
创建两个不同的布局以在适配器中使用,一个带广告,另一个不带广告。
覆盖getItemViewType()方法 public int getItemViewType(int position) { if (position % 10 == 0){ //每10个项目后广告 return 0; //使用整数常量来标识视图类型是Adview。 } return super.getItemViewType(position); }
  • 在OnCreateViewHolder()方法中

    @Override public ViewHolderClass onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == 0){ // 广告视图的常量 View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_row_with_ads, parent,false); return new ViewHolderClass(view, viewType); } View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_row, parent,false); return new ViewHolderClass(view); }

  • 在您的ViewholderClass中创建第二个构造函数,带有参数View和int

    public class ViewHolderClass extends RecyclerView.ViewHolder{ ... public ViewHolderClass(View view){ ... } public ViewHolderClass(View view, int viewType){ ... // 在此处初始化广告视图 }

  • 对于您的布局。 如果您的adapter_row.xml如下所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="8dp" >

    <android.support.v7.widget.CardView
        android:id="@+id/base"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        // your main content
    </android.support.v7.widget.CardView>
</RelativeLayout>
  • 接下来创建一个适配器布局文件 adapter_row_with_ads.xml,并进行如下更改。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="8dp" >

    <android.support.v7.widget.CardView
        android:id="@+id/base"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        // your main content

    </android.support.v7.widget.CardView>

      <!--This is where you'll add your AdView-->
      <com.google.android.gms.ads.AdView
          android:id="@+id/adView"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_below="@id/base"/>

</RelativeLayout>

这种方法可以减少电池的消耗和资源的消耗,使您的应用程序更加流畅。


我如何计算使用CardView时的高度和宽度? - amodkanthe
你可以在布局文件adapter_row_with_ads.xml中轻松定义它的XML。 - Mohammed Junaid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接