androidasynchronousactivity-oncreateview

onCreateView wait queries result


I need to execute a query to my DB to get some IDs and then use those IDs to execute another query to Realm DB and return the result to the Adapter which is used to create UI. My problem is that the adapter is created in onCreatView (main thread) and i need to let that wait queries result. Do you know how can i do? Really thanks :)

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    Realm realm = Realm.getDefaultInstance();
    cardList = new ArrayList(realm.where(Card.class).findAll().sort("rarity"));
    View rootView = inflater.inflate(R.layout.inventory_fragment_layout, null);
    RecyclerView recyclerView = rootView.findViewById(R.id.inventory_recycler);
    recyclerView.setLayoutManager(new GridLayoutManager(this.getContext(), 2));
    adapter = new inventoryFragmentRecyclerAdapter(this.getContext(), getCards()); <----- getCards() is used here.
    adapter.setClickListener(this);
    recyclerView.setAdapter(adapter);
    TextView topText = rootView.findViewById(R.id.inv_topText);
    topText.setTypeface(Typeface.createFromAsset(getActivity().getAssets(), "fonts/Square.ttf"));

    return rootView;
}



.
.
.
.
.
.



public List<Card> getCards() { //It is used when adapter is created, and it need to contain all cards to display

    //Realm realm = Realm.getDefaultInstance();

    String urlToGet = "myurl";
    String user_name = settings.getString("username", null);

    OkHttpClient client = new OkHttpClient();

    RequestBody formBody = new FormBody.Builder()
            .add("user_name", user_name)
            .build();

    Request request = new Request.Builder()
            .url(urlToGet)
            .post(formBody)
            .build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();
        }

        @Override
        public void onResponse(Call call, final Response response) throws IOException {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }

            responseCardInInventory = response.body().string();

            handler.post(new Runnable() {
                @Override
                public void run() {

                    List<CardInInv> cardListInInv = new ArrayList<>();

                    Gson gson = new Gson();
                    CardInInventory civ = gson.fromJson(responseCardInInventory, CardInInventory.class);
                    cardListInInv = getCards(civ);

                    //HERE I NEED TO USE REALM TO EXECUTE A QUERY USING cardListInInv


                }
            });
        }
    });

    //HERE I NEED TO RETURN THE RESULT OF THE QUERY EXECUTED BEFORE
    return cardsIninv;

}

EDIT 1: Hre is my adapter code

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

private List<Card> dataCard = new ArrayList<>();
private LayoutInflater mInflater;
private ItemClickListener mClickListener;


// data is passed into the constructor
public inventoryFragmentRecyclerAdapter(Context context, List<Card> data) {
    this.mInflater = LayoutInflater.from(context);
    this.dataCard = data;
}

// inflates the cell layout from xml when needed
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = mInflater.inflate(R.layout.inventory_rw, parent, false);
    return new ViewHolder(view);
}

// binds the data to the in each cell
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    holder.cardImage.setImageBitmap(BitmapFactory.decodeByteArray(dataCard.get(position).getCardImage(), 0, dataCard.get(position).getCardImage().length));
}

// total number of cells
@Override
public int getItemCount() {
    return dataCard.size();
}


// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    ImageView cardImage;

    //instanzio le componenti della pagina

    ViewHolder(View itemView) {
        super(itemView);

        cardImage = itemView.findViewById(R.id.inv_rw_cardimage);
        itemView.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
    }
}

// convenience method for getting data at click position
Card getItem(int id) {
    return dataCard.get(id);
}

// allows clicks events to be caught
public void setClickListener(ItemClickListener itemClickListener) {
    this.mClickListener = itemClickListener;
}

// parent activity will implement this method to respond to click events
public interface ItemClickListener {
    void onItemClick(View view, int position);
}
}

Solution

  • Move your query to your adapter and start your adapter with an empty list. Make your query call at the end of your constructor. When you've successfully finished your query, notify your adapter that it has changed and let it handle the changes with your new data at the end of your queries finishing successfully. So after doing that your adapter would look something like this.

    public inventoryFragmentRecyclerAdapter(Context context, List<Card> data) {
        this.mInflater = LayoutInflater.from(context);
        getCards();
    }
    
    public void getCards() { //It is used when adapter is created, and it need to contain all cards to display
    //Realm realm = Realm.getDefaultInstance();
    
    String urlToGet = "myurl";
    String user_name = settings.getString("username", null);
    
    OkHttpClient client = new OkHttpClient();
    
    RequestBody formBody = new FormBody.Builder()
            .add("user_name", user_name)
            .build();
    
    Request request = new Request.Builder()
            .url(urlToGet)
            .post(formBody)
            .build();
    
    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();
        }
    
        @Override
        public void onResponse(Call call, final Response response) throws IOException {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
    
            responseCardInInventory = response.body().string();
    
            handler.post(new Runnable() {
                @Override
                public void run() {
    
                    List<CardInInv> cardListInInv = new ArrayList<>();
    
                    Gson gson = new Gson();
                    CardInInventory civ = gson.fromJson(responseCardInInventory, CardInInventory.class);
                    cardListInInv = getCards(civ);
    
                    //use realm to do all your card inventory stuff to get your resulting object
                    dataCard = yourObjectListAfterUsingRealm;
                    notifyDataSetChanged();
                }
            });
        }
    });
    }