When I do adapter.notifyDataSetChanged() into onProductDetailsResponse it seems that the callback stays pending and the Recycleview doesn't show anything
I'm upgrading the Google Play Billing Library on my app, form 3 highter, I've the same issue on 4.1 and 5.
I retrieve my Subscriptions as Google require:
Define my productId
List<String> skuList = Application.getSubscritionsSkuList();
for (String sku : skuList) {
List<Product> productList.add(Product.newBuilder()
.setProductId(sku)
.setProductType(BillingClient.ProductType.SUBS)
.build());
Define my RecycleView and set My adapter
RecyclerView recyclerView = getActivity().findViewById(R.id.SubscritionsList);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
SubscriptionAdapter subscriptionAdapter = new SubscriptionAdapter(
context.getApplicationContext(), getActivity(), inventoryAsyncSub);
recyclerView.setAdapter(subscriptionAdapter);
Then retrieve the Subscriptions form the Store
QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
.setProductList(productList)
.build();
billingClient.queryProductDetailsAsync(
params,
new ProductDetailsResponseListener() {
public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) {
inventoryAsyncSub.addAll(productDetailsList);
subscriptionAdapter.notifyDataSetChanged();
}
}
);
The issue is: when I do subscriptionAdapter.notifyDataSetChanged() it seems that the callback from queryProductDetailsAsync stays pending and the Recycleview doesn't show anything till I scroll it and navigating out from this Fragment the app stays waiting something: no other callback works
First I thought that it depend form deprecated method querySkuDetailsAsync() so following the Google guide I migrated to queryProductDetailsAsync method, but the issue still persist.
My Adapter has got any of characteristic:
public class SubscriptionAdapter extends RecyclerView.Adapter<SubscriptionAdapter.Viewholder>{
public Object setOnItemClickListener;
private Context context;
private Activity activity;
private List<ProductDetails> InventoryAsyncSub;
private static ClickListener clickListener;
public SubscriptionAdapter(
Context context,
Activity activity,
List<ProductDetails> InventoryAsyncSub
) {
this.context = context;
this.activity = activity;
this.InventoryAsyncSub = InventoryAsyncSub;
}
@NonNull
@Override
public SubscriptionAdapter.Viewholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.subscrition_card, parent, false);
return new Viewholder(view);
}
@Override
public void onBindViewHolder(@NonNull SubscriptionAdapter.Viewholder holder, int position) {
ProductDetails subScr = InventoryAsyncSub.get( position );
PurchaseHandlerTools.setItemTitle( activity, holder.name, subScr.getTitle() );
holder.description.setText( subScr.getDescription() );
holder.pricesBox.findViewById( R.id.item_price);
TextView price = holder.pricesBox.findViewById( R.id.item_price);
price.setText( subScr.getSubscriptionOfferDetails().get(0).getPricingPhases().getPricingPhaseList().get(0).getFormattedPrice() );
}
@Override
public int getItemCount() {
return InventoryAsyncSub.size();
}
// stores and recycles views as they are scrolled off screen
public class Viewholder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView name;
private TextView description;
private LinearLayout pricesBox;
public Viewholder(@NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.submition_name);
description = itemView.findViewById(R.id.submition_description);
pricesBox = itemView.findViewById(R.id.purchase_btn);
itemView.setOnClickListener( this::onClick );
}
@Override
public void onClick(View v) {
clickListener.onItemClick( getAdapterPosition(), v );
}
}
public void setOnItemClickListener(ClickListener clickListener) {
SubscriptionAdapter.clickListener = clickListener;
}
public interface ClickListener{
void onItemClick( int position, View view );
}
}
Had the same issue and it is quite annoying since the docs don't tell you about it but the
onProductDetailsResponseis somehow blocking the UI thread. I couldn't even show a simply dialog in this listener.Therefore you have to put every UI modification to the UI thread like this and it works like a charm for me: