I am doing an escape game where I have a useObjectButton. When clicked, it shows a dialog with a ListView and I would like it to update the info once the player clicks on an item of the dialog. However, it is updated instantly and I don't know how to fix it.
My dialog is shown like this:
public Inventory.ITEM selectItem() {
if (game.inventory.isEmpty()) {
Toast.makeText(this, "Inventory is empty", Toast.LENGTH_SHORT).show();
return null;
} else {
AlertDialog inventoryDialog;
AlertDialog.Builder inventoryDialogBuilder = new AlertDialog.Builder(ActivityGame.this);
View inventoryPopup = getLayoutInflater().inflate(R.layout.inventory, null, false);
inventoryDialogBuilder.setView(inventoryPopup);
inventoryDialog = inventoryDialogBuilder.create();
inventoryDialog.setCancelable(true);
ListView lvInventory = inventoryPopup.findViewById(R.id.inventory_lv);
if (!game.inventory.isEmpty()) {
ArrayAdapter adapter = new ArrayAdapter(ActivityGame.this, android.R.layout.simple_list_item_1, game.inventory.getInventory());
lvInventory.setAdapter(adapter);
lvInventory.setOnItemClickListener((parent, view, position, id) -> {
selectedItem = game.inventory.getItem(position);
inventoryDialog.dismiss();
});
inventoryDialog.show();
}
}
}
And I call it in various functions like this one:
btnUseObject.setOnClickListener(v -> {
Inventory.ITEM item=selectItem();
info.setText(game.nightStand.useObject(item));
if(game.nightStand.isUnlocked()) {
btnDrawer1.setEnabled(true);
btnDrawer2.setEnabled(true);
}
});
First of all, you must understand the asynchronous nature of these instructions:
Inventory.ITEM item=selectItem();
and
lvInventory.setOnItemClickListener((parent, view, position, id) -> {
selectedItem = game.inventory.getItem(position);
inventoryDialog.dismiss();
});
You can't have this method returning the value of the selectedItem since it is unknown at the time of execution. Binding a click listener to a button happens at a different moment from the action of the user actually clicking the button. What you should do is give a function as a parameter to the asynchronous function that gets called when an user clicks the button. Something like this:
public void selectItem(Consumer callbackFn) {
if (game.inventory.isEmpty()) {
Toast.makeText(this, "Inventory is empty", Toast.LENGTH_SHORT).show();
return;
}
AlertDialog inventoryDialog;
AlertDialog.Builder inventoryDialogBuilder = new AlertDialog.Builder(ActivityGame.this);
View inventoryPopup = getLayoutInflater().inflate(R.layout.inventory, null, false);
inventoryDialogBuilder.setView(inventoryPopup);
inventoryDialog = inventoryDialogBuilder.create();
inventoryDialog.setCancelable(true);
ListView lvInventory = inventoryPopup.findViewById(R.id.inventory_lv);
ArrayAdapter adapter = new ArrayAdapter(ActivityGame.this, android.R.layout.simple_list_item_1, game.inventory.getInventory());
lvInventory.setAdapter(adapter);
lvInventory.setOnItemClickListener((parent, view, position, id) -> {
// The asynchronous function that gets called whenever an user clicks a button.
// You cannot return a value from it because it is not immediately known at execution time.
callbackFn.accept(game.inventory.getItem(position));
inventoryDialog.dismiss();
});
inventoryDialog.show();
}
And then
btnUseObject.setOnClickListener(v -> {
Consumer callbackFn = (Inventory.ITEM item) -> {
info.setText(game.nightStand.useObject(item));
if (game.nightStand.isUnlocked()) {
btnDrawer1.setEnabled(true);
btnDrawer2.setEnabled(true);
}
};
selectItem(callbackFn); // When an user clicks the button, please execute my callback function
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.