0

I am trying to add a sliding banner to the first row of a vertical RecyclerView in Android. When referenced in an Activity and outside my RecyclerView, it works fine but when I attempt to use it in the RecyclerView, I get a null pointer exception on the ViewPager object.

If I comment out this first row feature, the RecyclerView gets loaded successfully and populates all rows.

Error Message

   java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.view.ViewPager.setAdapter(android.support.v4.view.PagerAdapter)' on a null object reference
                      at media.client.clientmediaandroid.activity.home.ListCategoryAdapter$CategoryViewHolder.init(ListCategoryAdapter.java:136)
                      at media.client.clientmediaandroid.activity.home.ListCategoryAdapter$CategoryViewHolder.<init>(ListCategoryAdapter.java:109)
                      at media.client.clientmediaandroid.activity.home.ListCategoryAdapter.onCreateViewHolder(ListCategoryAdapter.java:53)
                      at media.client.clientmediaandroid.activity.home.ListCategoryAdapter.onCreateViewHolder(ListCategoryAdapter.java:31)
                      at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6493)
                      at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5680)
                      at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5563)
                      at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5559)
                      at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2229)
                      at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1556)
                      at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1516)
                      at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:608)
                      at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3693)
                      at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:3109)
                      at android.view.View.measure(View.java:19734)
                      at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
                      at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
                      at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
                      at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
                      at android.view.View.measure(View.java:19734)
                      at android.support.constraint.ConstraintLayout.internalMeasureChildren(ConstraintLayout.java:934)
                      at android.support.constraint.ConstraintLayout.onMeasure(ConstraintLayout.java:973)
                      at android.view.View.measure(View.java:19734)
                      at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
                      at android.support.design.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:714)
                      at android.support.design.widget.HeaderScrollingViewBehavior.onMeasureChild(HeaderScrollingViewBehavior.java:91)
                      at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onMeasureChild(AppBarLayout.java:1361)
                      at android.support.design.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:784)
                      at android.view.View.measure(View.java:19734)
                      at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1060)
                      at android.view.View.measure(View.java:19734)
                      at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
                      at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
                      at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:139)
                      at android.view.View.measure(View.java:19734)
                      at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
                      at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
                      at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
                      at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
                      at android.view.View.measure(View.java:19734)
                      at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
                      at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
                      at android.view.View.measure(View.java:19734)
                      at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
                      at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
                      at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
                      at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
E/AndroidRuntime:     at android.view.View.measure(View.java:19734)
                      at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
                      at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
                      at com.android.internal.policy.DecorView.onMeasure(DecorView.java:687)
                      at android.view.View.measure(View.java:19734)
                      at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2271)
                      at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1358)
                      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1607)
                      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1246)
                      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6301)
                      at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871)
                      at android.view.Choreographer.doCallbacks(Choreographer.java:683)
                      at android.view.Choreographer.doFrame(Choreographer.java:619)
                      at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
                      at android.os.Handler.handleCallback(Handler.java:751)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6077)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

ListCategoryAdapter.java

    public class ListCategoryAdapter extends RecyclerView.Adapter<ListCategoryAdapter.CategoryViewHolder> {

    private LayoutInflater inflater;
    private HomeView mHomeView;
    private List<MediaCategoriesResponseDTO> datum;

    public ListCategoryAdapter(HomeView mHomeView, List<MediaCategoriesResponseDTO> dt) {
        this.mHomeView = mHomeView;
        this.datum = dt;
    }
    @Override
    public CategoryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        CategoryViewHolder holder = null;
        CardView view = null;
        inflater = LayoutInflater.from(parent.getContext());

        if (viewType == 1) {

            // inflate your first item layout & return that viewHolder
            view = (CardView) inflater.inflate(R.layout.list_item_media_banner, parent, false);


            holder = new CategoryViewHolder(mHomeView, view, new ArrayList<Media>());

        } else {

            // inflate your second item layout & return that viewHolder
            view = (CardView) inflater.inflate(R.layout.list_item_media_category, parent, false);


            holder = new CategoryViewHolder(mHomeView, view, new ArrayList<Media>());

        }

        return holder;
    }

    @Override
    public void onBindViewHolder(CategoryViewHolder holder, int position) {
        if(position > 0) {
            holder.textViewCategoryName.setText(datum.get(position).getName());
        }
    }

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

    @Override
    public int getItemViewType(int position) {
        if (position == 0) return 1;
        else return 2;
    }

    public static class CategoryViewHolder extends RecyclerView.ViewHolder {
        //private HomeView mHomeView;

        private static ViewPager mPager;
        private static int currentPage = 0;
        private static int NUM_PAGES = 0;
        private ArrayList<ImageModel> imageModelArrayList;

        private int[] myImageList = new int[]{R.drawable.landing_screen_1, R.drawable.landing_screen_2,
                R.drawable.landing_screen_3};

        public TextView textViewCategoryName;

        public CategoryViewHolder(HomeView mHomeView, CardView cardView, List<Media> medias) {
            super(cardView);

            //this.mHomeView = mHomeView;

            textViewCategoryName = (TextView) cardView.findViewById(R.id.textViewCategoryName);

            imageModelArrayList = new ArrayList<>();
            imageModelArrayList = populateList();

            init(mHomeView);

            RecyclerView horizontalMediaRecyclerView = cardView.findViewById(R.id.list_item_media);

            LinearLayoutManager mLayoutManager = new LinearLayoutManager((Context)mHomeView, LinearLayoutManager.HORIZONTAL, false);

//            HomePresenter presenter = new HomePresenterImpl(mHomeView, new HomeInteractorImpl(), mLayoutManager,null, horizontalMediaRecyclerView);
//            presenter.loadMediaFeed(medias);

        }

        private ArrayList<ImageModel> populateList(){

            ArrayList<ImageModel> list = new ArrayList<>();

            for(int i = 0; i < 3; i++){
                ImageModel imageModel = new ImageModel();
                imageModel.setImage_drawable(myImageList[i]);
                list.add(imageModel);
            }

            return list;
        }

        private void init(HomeView mHomeView) {

            mPager = (ViewPager) ((AppCompatActivity)mHomeView).findViewById(R.id.pager_home);
            mPager.setAdapter(new SlidingImage_Adapter((AppCompatActivity) mHomeView, imageModelArrayList));

            CirclePageIndicator indicator = (CirclePageIndicator)
                    ((AppCompatActivity)mHomeView).findViewById(R.id.indicator_home);

            indicator.setViewPager(mPager);

            final float density = ((AppCompatActivity)mHomeView).getResources().getDisplayMetrics().density;

//Set circle indicator radius
            indicator.setRadius(5 * density);

            NUM_PAGES =imageModelArrayList.size();

            // Auto start of viewpager
            final Handler handler = new Handler();
            final Runnable Update = new Runnable() {
                public void run() {
                    if (currentPage == NUM_PAGES) {
                        currentPage = 0;
                    }
                    mPager.setCurrentItem(currentPage++, true);
                }
            };
            Timer swipeTimer = new Timer();
            swipeTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    handler.post(Update);
                }
            }, 3000, 3000);

            // Pager listener over indicator
            indicator.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

                @Override
                public void onPageSelected(int position) {
                    currentPage = position;

                }

                @Override
                public void onPageScrolled(int pos, float arg1, int arg2) {

                }

                @Override
                public void onPageScrollStateChanged(int pos) {

                }
            });

        }
    }
}

The NullPointer Exception is thrown at this line

mPager.setAdapter(new SlidingImage_Adapter((AppCompatActivity) mHomeView, imageModelArrayList));
sage
  • 587
  • 1
  • 8
  • 28
  • Can you please share your activity also? – NIKHIL NEDIYODATH Mar 22 '18 at 16:59
  • @NIKHILNEDIYODATH, I have added my Activity's onCreate method. I initially used the ViewPager directly from the Activity without any problems. My desire is to have it within the first row of the RecyclerView and remove the other one. – sage Mar 22 '18 at 17:29
  • 1
    If the `ViewPager` is supposed to be a `RecyclerView` item, it needs to be in the item layout, and that's where you need to look for it, not in the `Activity`. Handle it just like you're handling `textViewCategoryName`. – Mike M. Mar 22 '18 at 23:30
  • @MikeM., I have a separate layout for the ViewPager that I am inflating for the first row of the RecyclerView. I have modified the code accessing it from the cardView like so mPager = (ViewPager) cardView.findViewById(R.id.pager_home); – sage Mar 23 '18 at 00:28
  • 1
    Yeah, that's more like it. You shouldn't really be passing the `Activity` to the `ViewHolder` at all. I'm not sure, though, why you're using the same `CategoryViewHolder` for both view types. If the `ViewPager` isn't in the layout for the regular items, that's going to throw the same Exception when it tries to set one up. You should have separate `ViewHolder`s for each type. – Mike M. Mar 23 '18 at 00:42
  • @MikeM., I thought so too after seeing your first response. I will separate the ViewHolders. At the iteration by the Adapter, each element that is not present will throw a nullpointer, therefore different ViewHolders will do the job – sage Mar 23 '18 at 06:20
  • 1
    @MikeM., thank you very much for your guidance. I have resolved the issue. Creating separate ViewHolders and selecting between them based on the index or position being rendered by the RecyclerView did the trick. – sage Mar 24 '18 at 07:23
  • @MikeM., thanks for your help in this post. I would appreciate if you can help me take a look at a question that no one has answered yet - https://stackoverflow.com/questions/49235581/home-navigation-header-of-navigationdrawer-not-showing-in-simulator – sage Mar 26 '18 at 05:53

1 Answers1

0

With the help of @MikeM. and bit more research, I have resolved the issue. Creating separate ViewHolders and selecting or rendering them the applicable one based on the index or position being rendered by the RecyclerView did the trick.

Most of the work was done in the Adapter.

public class ListCategoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private LayoutInflater inflater;
private HomeView mHomeView;
private List<MediaCategoriesResponseDTO> datum;
private List<Media> listOfMedia;
CardView view;

public ListCategoryAdapter(HomeView mHomeView, List<MediaCategoriesResponseDTO> dt) {
    this.mHomeView = mHomeView;
    this.datum = dt;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    inflater = LayoutInflater.from(parent.getContext());

    if (viewType == 1) {

        // inflate your first item layout & return that viewHolder
        view = (CardView) inflater.inflate(R.layout.list_item_media_banner, parent, false);


        return new MediaBannerViewHolder(mHomeView, view);

    } else {

        // inflate your second item layout & return that viewHolder

        view = (CardView) inflater.inflate(R.layout.list_item_media_category, parent, false);


        return new CategoryViewHolder(mHomeView, view);

    }

}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if(position > 0) {

        ((CategoryViewHolder)holder).textViewCategoryName.setText(datum.get(position).getName());
        listOfMedia = datum.get(position).getMedias();
        RecyclerView horizontalMediaRecyclerView = view.findViewById(R.id.list_item_media);

        LinearLayoutManager mLayoutManager = new LinearLayoutManager((Context)mHomeView, LinearLayoutManager.HORIZONTAL, false);
        horizontalMediaRecyclerView.setLayoutManager(mLayoutManager);
        horizontalMediaRecyclerView.setHasFixedSize(true);
        HomePresenter presenter = new HomePresenterImpl(mHomeView);
        presenter.loadMediaFeed(listOfMedia, horizontalMediaRecyclerView);
    }

    //Manipulate ViewPager View here
}

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

@Override
public int getItemViewType(int position) {
    if (position == 0) return 1;
    else return 2;
}

public static class CategoryViewHolder extends RecyclerView.ViewHolder {

    public TextView textViewCategoryName;

    public CategoryViewHolder(HomeView mHomeView, CardView cardView) {
        super(cardView);


        textViewCategoryName = (TextView) cardView.findViewById(R.id.textViewCategoryName);
    }
}

public static class MediaBannerViewHolder extends RecyclerView.ViewHolder {
    //The ViewPager code here
}

}

sage
  • 587
  • 1
  • 8
  • 28