4

In my android app I'm trying to implement mopub native ads. Before using these native ads my app was functioning correctly as expected. Now it gives outofbound exceptions and incorrect items when list item is clicked. I'm using recyclerview and using infinite scrolling, it gets item from my api and displays item correctly, but when clicking on item it gives incorrect item.

Here is my recyclerview adapter below.

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;
    }
}

And I'm using guide given here to show ads https://dev.twitter.com/mopub/native/native-android-sdk-integration

Please help. what I can/should do to resolve this.

Thanks in advance.

lightsaber
  • 1,411
  • 18
  • 36
  • I am also facing the same issue , did you resolved this issue ?? post your answer if you have solved your problem . thank u – shobhan Oct 25 '17 at 09:44

1 Answers1

3

I know this is an old question, but I was looking for the answer for a couple of hours. Probably I'll save someone's time with this solution.

If you will look carefully documentation here: https://github.com/mopub/mopub-android-sdk/wiki/Native-Ads-with-Recycler-View you will find this:

If you register any data observers on your original Adapter, you should instead register them on the MoPubRecyclerAdapter so they will receive messages with the adjusted position of content items. If you do not do this, the positions you receive for insertion and removal messages may be inaccurate. Be sure to check isAd(position) and use MoPubRecyclerAdapter#getOriginalPosition if you need the position of the item in your local adapter.

So, to get real position, it is necessary to use MoPubRecyclerAdapter.getOriginalPosition(position_in_your_adapter) method.

tonyAndr
  • 157
  • 1
  • 2
  • 10
  • OMG. You are a lifesaver. Thanks - i had the exact same issue and thought I would have to do some maths to get back to the original position. Thanks so much! +! – Simon Mar 27 '16 at 08:26