• 4
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

Context

I have an activity where a user clicks hit or miss for three turns and then it is the computers turn, to click hit or miss.

The problem

The problem is when it is the computers turn the program hangs the recycler view and makes multiple clicking sounds before eventually displaying the a result. You can see this here:

enter image description here

What I've tried

Through some troubleshooting I seen that I should preform the computers task in a background thread and any UI changes should be preformed in the runOnUiThread. So I have this (this is the onClickEvent):

AsyncTask.execute(new Runnable() {
                @Override
                public void run() {
                    playerHit(whosThrowing);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            setAdapterToDisplayStats(whosThrowing);
                            tv_numberToHit.setText(numToHit.get(whosThrowing));
                            if(amountThrownThisRound == 3 && (!opponent.equals("SINGLE"))) {
                                nextPlayerTurn(whosThrowing);
                            }
                        }
                    });
                }
            });
            break;
        case R.id.btn_miss:
            AsyncTask.execute(new Runnable() {
                @Override
                public void run() {
                    playerMissed(whosThrowing);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            setAdapterToDisplayStats(whosThrowing);
                            //Player threw their three darts. Change player.
                            if(amountThrownThisRound == 3 && (!opponent.equals("SINGLE"))) {
                                nextPlayerTurn(whosThrowing);
                            }
                        }
                    });
                }
            });
            break;

However this didn't solve the problem and the GIF above actually shows the result of this code. I designed this first for a Human v Human scenario and then started implementing a Human V Computer scenario. I thought this would have been straight forward get a result for the computer either hit or miss and perfomClick() on the relevant button.

As you can see in the above code block, the majority of the methods are in the runOnUiThread this is because these methods contain at least one bit of code that changes the UI but parts that doesn't mess with the UI. I can't imagine I have to go through and wrap each line of code in a run in background or run in UI thread, surely? Just when it is the computers turn.

The setAdapterToDisplayStats(whosThrowing); calls onBindViewHolder in a separate class which updates the recylerview. Does having just setAdapterToDisplayStats(whosThrowing) ensure that anything after it even if it is in a separate class runsOnTheUi thread?

Code that may be having an effect

Computers throw

 if(opponent.equals("COMPUTER") && confirmedPlayers.get(0).equals("A.I") && Integer.parseInt(amountThrown.get(0)) % 3  == 0){
        btn_hit.setEnabled(false);
        btn_miss.setEnabled(false);
        for (int i = 0; i < 3; i++) {
            takeCompThrow();
        }
        btn_hit.setEnabled(true);
        btn_miss.setEnabled(true);
    }
    return whosThrowing;

Computers performClick

The preformClick was what I had originally wrapped in a runnable block, thinking anything I called after it would be done in the background thread. Although this is where I first ran into the problem and moved it to the onClick() as I read the UI should be done separately but still no joy.

private void takeCompThrow() {
        boolean hitOrMiss = computerThrow.computerHitOrMiss(compLevel);
        if(hitOrMiss) {
            btn_hit.performClick();
        } else {
            btn_miss.performClick();

Here's how it preforms Human V Human in case that's important:

enter image description here

The main question

Where am I going wrong?

In my opinion the problem is related with this code block, because you are trying to update recyclerview for multiple times in a really short period.

for (int i = 0; i < 3; i++) {
  takeCompThrow();
}

Since you are the owner of the calculation logic, you can directly play turns and update the result directly without performing clicks. In this regard, there is no need to use any async task, unless there is a huge calculation cost. My first suggestion, you can do sth like this:

if this is computer turn
  for 1..3
    calculate result for the computer turn
  update recyclerview

There is a second option, but I'd go definitely with the above . Even though it will be a quick solution but won't be the best. You just need to put delay between computer clicks in order to let Recyclerview to calculate and redraw elements. So it will be like with the existing code :

for (int i = 0; i < 3; i++) {
  takeCompThrow();
  someDelay();
}
  • 1
Reply Report
      • 2
    • I said second solution meaning your first solution. I keep thinking it is your second solution because of the code block above it, where you were quoting my code.
      • 1
    • I actually suspected that for loop as well, and replaced it with three takeCompThrow(); one after the other to troubleshoot but no joy. I will try your suggetions and report back.
      • 1
    • Your second solution worked exactly as I wanted. All I did was copy and paste the methods that were in my onClickEvent and used these instead of btn_hit.performClick(); which logically does the exact same thing. I'm clueless as to why this would be, and would be intrigued to know if anyone reading this could explain. Thanks a lot anyway! I got too deep into fixing the background task, instead of taking a step back and thinking of doing it your way of thinking.