【问题标题】:Android: Implementing mopub native ads in recyclerview gives incorrect item positions and IndexOutOfBoundsExceptionAndroid:在 recyclerview 中实施 mopub 原生广告会导致不正确的项目位置和 IndexOutOfBoundsException
【发布时间】:2026-01-11 19:30:02
【问题描述】:

在我的 android 应用中,我正在尝试实现 mopub 原生广告。在使用这些原生广告之前,我的应用程序按预期正常运行。现在,当单击列表项时,它会给出出站异常和不正确的项。我正在使用 recyclerview 并使用无限滚动,它从我的 api 获取项目并正确显示项目,但是当单击项目时它会给出不正确的项目。

下面是我的 recyclerview 适配器。

package com.example.adapters;

import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.MyApplication;
import com.example.R;
import com.example.events.ErrorLoadingFeed;
import com.example.events.FeedLoaded;
import com.example.events.LoadMoreFeed;
import com.example.model.Post;
import com.example.model.Pagination;
import com.example.ui.InfoActivity;
import com.example.utils.MyAppConstants;
import com.google.gson.Gson;
import com.squareup.picasso.Picasso;

import java.util.List;

import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Header;
import retrofit.client.Response;

/**
 * Created by starwar on 08/09/15.
 */
public class PostRecycleAdapter extends RecyclerView.Adapter<com.example.adapters.PostRecycleAdapter.PostViewHolder> implements Callback<List<Post>> {

    private Context mContext;
    private List<Post> mPosts;
    // Allows to remember the last item shown on screen
    private int lastPosition = -1;
    //    Pagination
    private Pagination mPagination;

    public PostRecycleAdapter(Context context, List<Post> posts) {
        mContext = context;
        mPosts = posts;
    }

    @Override
    public PostViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item, parent, false);

        PostViewHolder viewHolder = new PostViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(PostViewHolder holder, int position) {
        holder.bindPost(mPosts.get(position));
        // Here you apply the animation when the view is bound
        setAnimation(holder.mPostName, position);

        //check for last item
        if ((position >= getItemCount() - 1)) {
            // Loading next set of list items on scroll
            if (mPagination != null && !mPagination.getOutOfRange() && mPagination.getNextPage() != null){
                MyApplication.bus.post(new LoadMoreFeed(mPagination));
            }
        }
    }

    @Override
    public int getItemCount() {
        return mPosts == null ? 0 : mPosts.size();
    }

    /**
     * Here is the key method to apply the animation
     */
    private void setAnimation(View viewToAnimate, int position)
    {
        // If the bound view wasn't previously displayed on screen, it's animated
        if (position > lastPosition)
        {
            Animation animation = AnimationUtils.loadAnimation(mContext, android.R.anim.slide_in_left);
            viewToAnimate.startAnimation(animation);
            lastPosition = position;
        }
    }

    public class PostViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public TextView mPostName;
        public ImageView mAnchorImage;

        public PostViewHolder(View itemView) {
            super(itemView);

            mPostName = (TextView) itemView.findViewById(R.id.postName);
            mAnchorImage = (ImageView) itemView.findViewById(R.id.anchorImage);

            itemView.setOnClickListener(this);
        }

        public void bindPost(Post post) {
            mPostName.setText(post.getName());

            String postImage = post.getPostImage();
            Picasso.with(mContext)
                    .load(postImage)
                    .placeholder(R.drawable.avatar_empty)
                    .into(mAnchorImage);
        }

        @Override
        public void onClick(View view) {
            int position = getAdapterPosition(); // gets item position
            Post post = mPosts.get(position);
            int postId = post.getId();
            String postName = post.getName();

            Intent intent = new Intent(mContext, InfoActivity.class);
            intent.putExtra(MyAppConstants.POST_ID, postId);
            intent.putExtra(MyAppConstants.POST_NAME, postName);
            mContext.startActivity(intent);
        }
    }

    @Override
    public void success(List<Post> posts, Response response) {
        if (mPosts == null) {
            mPosts = posts;
        } else {
            mPosts.addAll(posts);
        }

        notifyDataSetChanged();

        List<Header> headerList = response.getHeaders();
        for(Header header : headerList) {
            if ("X-Pagination".equals(header.getName())) {
                Gson gson = new Gson();
                mPagination = gson.fromJson(header.getValue(), Pagination.class);
            }
        }

        MyApplication.bus.post(new FeedLoaded(mPagination));
    }

    @Override
    public void failure(RetrofitError error) {
        Log.d("Call", " : Failed => " + error);
        MyApplication.bus.post(new ErrorLoadingFeed(error));
    }

    public void clearData() {
        if (mPosts != null) {
            mPosts.clear();
            notifyDataSetChanged();
        }
    }

    public List<Post> getPosts() {
        return mPosts;
    }
}

我正在使用此处提供的指南来展示广告 https://dev.twitter.com/mopub/native/native-android-sdk-integration

请帮忙。我可以/应该做些什么来解决这个问题。

提前致谢。

【问题讨论】:

  • 我也遇到了同样的问题,请问您解决了吗??如果您解决了问题,请发布您的答案。谢谢你

标签: android android-recyclerview mopub twitter-fabric


【解决方案1】:

我知道这是一个老问题,但我花了几个小时寻找答案。也许我会用这个解决方案节省别人的时间。

如果您仔细查看此处的文档:https://github.com/mopub/mopub-android-sdk/wiki/Native-Ads-with-Recycler-View,您会发现:

如果您在原始适配器上注册任何数据观察器,则应改为在 MoPubRecyclerAdapter 上注册它们,以便它们接收到内容项位置已调整的消息。如果您不这样做,您收到的插入和删除消息的位置可能不准确。如果您需要项目在本地适配器中的位置,请务必检查 isAd(position) 并使用 MoPubRecyclerAdapter#getOriginalPosition。

所以,要获得真实的位置,需要使用 MoPubRecyclerAdapter.getOriginalPosition(position_in_your_adapter) 方法。

【讨论】:

  • 天啊。你是救生员。谢谢 - 我有完全相同的问题,并认为我必须做一些数学才能回到原来的位置。非常感谢! +!
最近更新 更多