Search code examples
androidandroid-viewpager

ViewPager - TabLayout with LiveData


I have a list of products in a recycler view. once an item is pressed it will take u to the second activity to show more info related to that product. I'm trying to implement viewPager. was following a tutorial from CodingWithMitch but in his example, he has random data and could easily fetch them.

ArrayList<Fragment> fragments = new ArrayList<>();
    Hat[] hats = Hats.getHats();
    for(Hat hat: hats){
        ViewPagerItemFragment fragment = ViewPagerItemFragment.getInstance(hat);
        fragments.add(fragment);
    }
    MyPagerAdapter pagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), fragments);
    mMyViewPager.setAdapter(pagerAdapter);
    mTabLayout.setupWithViewPager(mMyViewPager, true);

Unfortunately, for me, the data r fetched from Livedata object. How do I loop or iterate over the livedata to extract all the products object so I can set the fragments!

ArrayList<Fragment> fragments = new ArrayList<>();
    final MarketViewModel marketViewModel = new ViewModelProvider(this).get(MarketViewModel.class);
    MutableLiveData<List<Product>> products = marketViewModel.getProductInfo("parentID");
    //What to do here !!!
    /*for (:) {
        ProductInfoFragment fragment = ProductInfoFragment.getInstance(products);
        fragments.add(fragment);
    }*/
    ProductPagerAdapter adapter = new ProductPagerAdapter(getSupportFragmentManager(), 0, fragments);
    viewPager.setAdapter(adapter);
    tabLayout.setupWithViewPager(viewPager, true);

also, this shows the whole products. but how to show the pressed item first. the one that the user clicked. and then the user will be able to swap left and right browsing the whole list!?

Edit: I tried this! but now it shows a blank white page.

ArrayList<Fragment> fragments = new ArrayList<>();
    final MarketViewModel marketViewModel = new ViewModelProvider(this).get(MarketViewModel.class);
    marketViewModel.getProductInfo("parentID");
    marketViewModel.getProductInfo("parentID").observe(this, products -> {
        for (int i = 0; i < products.size(); i++) {
            Product product = products.get(i);
            ProductInfoFragment fragment = ProductInfoFragment.getInstance(product);
            fragments.add(fragment);
        }
    });
    ProductPagerAdapter adapter = new ProductPagerAdapter(getSupportFragmentManager(), 0, fragments);
    viewPager.setAdapter(adapter);
    tabLayout.setupWithViewPager(viewPager, true);

Solution

  • Please try to build the ViewPager adapter after your LiveData submits new data, as it seems that the ViewPager is initialized with a free-of-data adapter, where its code runs before LiveData got returned.

    So you would try:

    ArrayList<Fragment> fragments = new ArrayList<>();
        final MarketViewModel marketViewModel = new ViewModelProvider(this).get(MarketViewModel.class);
        marketViewModel.getProductInfo("parentID");
        marketViewModel.getProductInfo("parentID").observe(this, products -> {
            for (int i = 0; i < products.size(); i++) {
                Product product = products.get(i);
                ProductInfoFragment fragment = ProductInfoFragment.getInstance(product);
                fragments.add(fragment);
            }
    
            ProductPagerAdapter adapter = new ProductPagerAdapter(getSupportFragmentManager(), 0, fragments);
            viewPager.setAdapter(adapter);
            tabLayout.setupWithViewPager(viewPager, true);
    
        });
    

    Edit: I fixed the code but the issue persists. it shows blank while page looks like it got stuck into an infinite loop! It's so abnormal to me.

    Now I will be trying to just update the ViewPager fragments within the LiveData Observer without rebuilding the adapter.

    So, We'll keep the original code as-is, make the adapter as a class field, and call mAdapter.notifyDataSetChanged() for new data returned by LiveData.

    ProductPagerAdapter mAdapter;
    
    ArrayList<Fragment> fragments = new ArrayList<>();
        mAdapter = new ProductPagerAdapter(getSupportFragmentManager(), 0, fragments);
        viewPager.setAdapter(mAdapter);
        tabLayout.setupWithViewPager(viewPager, true);
    
        final MarketViewModel marketViewModel = new ViewModelProvider(this).get(MarketViewModel.class);
        marketViewModel.getProductInfo("parentID");
        marketViewModel.getProductInfo("parentID").observe(this, products -> {
            for (int i = 0; i < products.size(); i++) {
                Product product = products.get(i);
                ProductInfoFragment fragment = ProductInfoFragment.getInstance(product);
                fragments.add(fragment);
            }
    
             mAdapter.notifyDataSetChanged();  // <<<<<< here updating adapter fragemnts
    
        });
    
    

    Also, this answer may help you to update your adapter fragments correctly.