Как заставить метод приостановить и ждать ввода с Android? - PullRequest
2 голосов
/ 26 октября 2010

В основном я создал приложение для блэкджека, которое использует несколько методов, которые вызываются и передают длинную информацию, которая необходима (о картах и ​​действиях). У меня есть 2 кнопки, отображаемые на экране, которые можно нажимать (нажимать и стоять). Теперь у меня есть метод под названием Player Turn ... и это, когда у меня (через статические целые) есть, если кнопка выбрана, вещи будут происходить. Однако я сделал это с бесконечным циклом, думая, что он будет просто проверять, нажата ли кнопка, а затем выполнять действия только при нажатии кнопки. Это не работает, так как мой экран не обновляется после каждого изменения текстового или графического изображения, поэтому, как только я нажимаю на запуск игры, игра «зависает» (из-за того, что метод не заканчивается), и поэтому я не могу нажать на указанные кнопки , Есть ли способ вызвать что-то похожее на прослушиватель клавиатуры в Java (который приостанавливает активность и ждет ввода пользователя), в Android? Если нет, что бы вы предложили в качестве обходного пути? И наконец (хотя и не так важно в настоящее время), как бы я правильно обновлял все после каждого изменения (я считаю, что мне нужно использовать инвалидацию ... хотя я не уверен, что нужно иметь до аннулирования, чтобы она обновляла все это)? Большое спасибо заранее.

Ответы [ 5 ]

1 голос
/ 09 мая 2011

Подпрограммы обратного вызова Activity ждут последнего прослушивателя событий ... Может ли это быть простым решением ??

Этот вопрос «Ждать ввода пользователя» - это вопрос, который регулярно возникает, меня также озадачивает, и я еще не видел, что мне кажется реальным чистым решением.

Недавно у меня возникла идея, но я довольно зелен в игре для Android и хочу посмотреть, как она выдерживает проверку.

Техника основана на идее, что подпрограммы обратного вызова активности не завершаются, пока есть прослушиватель событий, который продолжает прослушивать. В результате подпрограмма обратного вызова выполняет последний оператор, а затем ничего не делает, но не завершается. (IOW, «вы можете проверить в любое время, когда захотите, но вы никогда не сможете уйти… пока слушатели событий не позволят вам». Юк.)

Это, кажется, соответствует требованиям. Пользовательский интерфейс не заморожен и нет бесконечного цикла. Единственное требование к пользовательскому интерфейсу - поддерживать список событий. Когда пользователь вводит ввод, процедура обратного вызова события, то есть onKey, обрабатывает ввод, а затем выполняет ВСЕ ШАГИ, ТРЕБУЕМЫЕ ПЕРЕД СЛЕДУЮЩИМ пользователем. Затем процедура обратного вызова события устанавливает нового слушателя и возвращает его, освобождая старого слушателя и оставляя пользовательский интерфейс с одной задачей - поддерживать нового слушателя. Это продолжается итеративно до тех пор, пока не будет завершена процедура обратного вызова активности.

Вот код, который я тестировал:

@Override   
    public void onCreate(Bundle savedInstanceState) {       
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main);
    }

         public void onStart() {
           super.onStart();

        final EditText et = (EditText) findViewById(R.id.edittext);
        et.setOnKeyListener(new OnKeyListener() {    
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                    boolean tf = checKey(keyCode, event);
                    if(tf==false)return false;
                    gotPW();
                    return true;
            }
        });
    }


         gotPW(){
               ...do ALL the stuff you want to do before you need more user input
               ...set ANOTHER event listener that is connected to another 
                  event callback method

               ...return, releasing the first event listener, and putting the onStart 
                  routine back in its same state -- nothing to do except to attend to 
                  an event listener.
         }



         //this checks to see if the enter key has been hit
         public boolean checKey(int keyCode, KeyEvent event){   
       if ((event.getAction() == KeyEvent.ACTION_DOWN) && 
                (keyCode == KeyEvent.KEYCODE_ENTER)) 
    {          
        return true;        
    }        
    return false;    
}

Вышеупомянутый код, кажется, делает то, что требуется ... onStart ждал моего ввода.

Это хорошая техника?

Есть ли проблемы, которые я не выявил?

Все это делали все время, и только новички вроде меня думают, что они к чему-то относятся?

1 голос
/ 12 апреля 2011

Похоже, новый Activity (вызванный startActivityForResult), и Handler (вызванный из onActivityResult) может решить вашу проблему.

Взгляните на приведенный ниже фрагмент кода:

activity interactions

Скажем, метод, которым вы хотите «спать», это doSomething из MainActivity класс.Я предполагаю, что это вызывается из некоторой реализации обработчика событий.Вы должны переместить все вызовы из этого метода в действие BackgroundActivity, которое должно отображать ProgressDialog и / или ничего другого.В вашем методе doSomething вы должны начать действие с намерения, указывающего на BackgroundActivity, с

this.startActivityForResult(new Intent(this, BackgroundActivity.class), 
    BG_ACTIVITY_ID);

, где BG_ACTIVITY_ID - ваш уникальный идентификатор запущенного действия, поэтому, когда оно заканчивается, вы можете обработать его.

Внутри processBackgroundData (или когда фоновая активность завершена), вы должны установить результат перед вызовом finish ():

final Intent intent = new Intent();
intent.putExtra(KEY_FOR_DATA_YOU_NEED, dataYouNeed);
setResult(Activity.RESULT_OK, intent);
finish();

В вашей MainActivity вы также должны переопределить onActivityResultметод, чтобы получить необходимую информацию из завершенной задачи BackgroundActivity:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    //you might also want to check if the resultCode is `Activity.RESULT_OK`...
    switch (requestCode)
    {
        case BG_ACTIVITY_ID:
            //get the data you need 
            final String dataYouNeed = data.getStringExtra(KEY_FOR_DATA_YOU_NEED);
            //process the data...
            //if necessary (threads!), call your backgroundHandler's 
            //sendMessage with the retrieved informations as obj.parameters
        [...]
            break;
        default:
            [...]
            break;
    }
}

И внутри вашего BackgroundHandler 'handleMessage метода (так как вы вернулись к потоку пользовательского интерфейса: потоку, в котором ваш главныйприложение работает) вы можете делать все необходимые изменения пользовательского интерфейса, а также прослушивать события пользователя.

Таким образом, вы избавляетесь от бесконечного цикла и всегда можете быть в курсе взаимодействия с пользователем.

0 голосов
/ 26 октября 2010

Хм У меня может быть неправильная интерпретация, но кажется, что выполнение setOnClickListener имеет его так, что, когда достигается определенная часть кода, кнопка становится доступной для нажатия и действия выполняются при нажатии кнопки? У меня уже есть так, что когда нажата кнопка и наступает ход игрока, действия будут происходить. Однако мне нужно знать, как заставить программу буквально ждать или останавливаться, пока не будет нажата одна из кнопок.

Аналогично тому, когда вы настраиваете клавиатуру, а Java ждет ввода с клавиатуры.

0 голосов
/ 02 ноября 2010

Не опрашивать, чтобы увидеть, была ли нажата ваша кнопка.Просто делайте все, что вы хотите, в OnClickHandler.

Вот пример того, как ваш код может выглядеть (Неправильный путь):

while(1) {
  if (buttonHitClicked()) {
    doHit();
  } else if (buttonStandClicked()) {
    doStand();
  }
  //sleep(); // won't help
}

И вот правильный путь:

OnClickListener hitListener = new OnClickListener() {
  public void onClick(View v) { doHit(); }
};
OnClickListener standListener = new OnClickListener() {
  public void onClick(View v) { doStand(); }
};

protected void OnCreate(Bundle savedValues) {
  ...

  Button hitButton = (Button)findViewById(R.id.hitButton);
  button.setOnClickListener(hitListener);

  Button standButton = (Button)findViewById(R.id.standButton);
  button.setOnClickListener(standListener);

  ...
}

Да, правильный путь включает в себя немного больше набора текста ... но он также работает .И если вы посмотрите на ссылку, опубликованную Коллином, есть менее «тип-у» способ сделать это, включающий добавление материала в ваш файл AndroidManifest.Вы просто указываете на функции в вашем классе с правильной сигнатурой (public void funcName(View v), насколько я помню), и Android обрабатывает все слушатели за вас.

Что касается "заставления вашей программы ждать", это уже .Код вашей программы не будет запущен, пока не будет сделан какой-либо вызов в одну из точек входа ваших классов.До тех пор выполнение в вашем процессе обрабатывается кодом обработчика пользовательского интерфейса Android, передавая сообщения туда и обратно.Как только одно из этих сообщений попадает в ваше приложение (onCreate, прослушиватель кликов и т. Д.), Ваш код делает свое дело и возвращает его, позволяя потоку пользовательского интерфейса вернуться к обработке всего ввода для процесса вашего приложения.

И если вашему приложению потребуется более 5 секунд, чтобы ответить на сообщение, оно будет убито системой с "ANR" ... Приложение не отвечает.

Еще одно удобное видео от Google IO , озаглавленное «Написание приложений для Android Zippy».

0 голосов
/ 26 октября 2010

Android запустит цикл обработки событий для вас - так что вам не придется обходить себя в ожидании ввода.

Вы можете подключиться к циклу несколькими способами.Начиная с версии 1.6, самый простой способ сделать это - указать хук в вашем XML, например:

В качестве альтернативы вы можете сделать это в коде, вызвав setOnClickListener.

Takeвзгляните на http://android -developers.blogspot.com / 2009/10 / ui-framework-changes-in-android-16.html для некоторых примеров (прочитайте раздел, озаглавленный «Прослушиватели с более простым щелчком»)

Если вы можете сделать недействительным свое представление, тогда цикл событий Android позаботится о перерисовке экрана, включая любые изменения макета.Если у вас есть пользовательские представления, их onDraw () будет вызываться соответствующим образом.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...