简体   繁体   中英

How to wait for Android Dialog to finish?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM