myLooper () не завершается во время асинхронной задачи - PullRequest
1 голос
/ 13 марта 2012

Я понимаю, что, возможно, делаю это немного задом наперед, но пока не нашел подходящего решения, и это самое близкое, что я нашел. Сначала я представляю представление «Вход в систему» ​​пользователю и отправляю введенные учетные данные в веб-службу, которая проверяет учетные данные и возвращает HTTP 200, если вход выполнен успешно. После успеха я делаю HTTP-запрос JSON к тому же веб-сервису для загрузки списка объектов JSON. Затем эти объекты анализируются и помещаются в базу данных SQLite. Есть около 100 или более объектов, поэтому асинхронная задача привлекательна, поэтому я не блокирую интерфейс. Смысл этого состоит в том, чтобы отобразить ProgressBar (неопределенный) пользователю, говорящему, что в фоновом режиме выполняется работа, а затем вернуть его в отдельное намерение после заполнения БД. Вот фрагменты кода:

Подтверждение логина и вызов действия входа:

switch(statusCode) {
   case 200:
      PrepareLogin doLogin = new PrepareLogin();
      doLogin.execute();
      if (doLogin.getStatus().equals(AsyncTask.Status.FINISHED)) {
         // Redirect to intent?
      }
      break;
   case 401:
      Toast.makeText(Login.this, "Invalid Username/Password", Toast.LENGTH_LONG).show();
}

Асинхронная задача с вспомогательными функциями в фоновом режиме:

private class PrepareLogin extends AsyncTask<Void,Void,Void> {
        ProgressDialog dialog;
        @Override
        protected void onPreExecute() {
            dialog = new ProgressDialog(Login.this);
            dialog.setTitle(getString(R.string.get_login_dialog_title));
            dialog.setMessage(getString(R.string.get_login_dialog_message));
            dialog.setIndeterminate(true);
            dialog.setCancelable(false);
            dialog.show();
        }
        @Override
        protected Void doInBackground(Void... params) {
            Looper.myLooper().prepare();
            Looper.myLooper().loop();
            DBHelper dbHelp = new DBHelper(Login.this);
            WSHelper wsHelp = new WSHelper();
            long timeNow = System.currentTimeMillis();
            dbHelp.resetDB(Login.this); // For dev environment only...remove in prod
            dbHelp.create();
            dbHelp.createUser(username, password, timeNow, "false");
            dbHelp.close();
            wsHelp.getEmployees(Login.this, username, password);
            Looper.myLooper().quit();
            return null;
        }
        protected void onPostExecute() {
            Intent myIntent = new Intent(login.getContext(), Main.class);
            startActivityForResult(myIntent, 0);
            dialog.dismiss();
        }
    }

Единственный способ заставить это функционировать без выдачи ошибки «Обработчик должен подготовить петлитель» - это функция Looper.myLooper.prepare().

Я вижу в журналах, что соединение установлено и БД заполнена, но диалоговое окно продолжает вращаться и никогда не достигает функции onPostExecute() задачи Async. Хотя он достигает линии Looper.myLooper().quit();.

Есть предложения?

Ответы [ 2 ]

0 голосов
/ 13 марта 2012

Похоже, что мой класс WSHelper пытался внести какие-то изменения в пользовательский интерфейс из фонового процесса.Удалив инициализацию wsHelp из AsyncTask и сделав ее константой, я смог продолжить работу очень хорошо.Также стоит отметить, что я изменил возвращаемое значение на void для метода wsHelp.getEmployees ().

0 голосов
/ 13 марта 2012

Если вы получаете сообщение «Обработчик должен подготовить петлитель», скорее всего, вы вызываете AsyncTask в неверном контексте. Я не помню, чтобы мне когда-либо приходилось явно вызывать функцию Looper.prepare() в любой AsyncTask. Как только вы избавитесь от петлителя, все будет в порядке, AsyncTask - один из самых простых в использовании классов в Android. Вы должны опубликовать свой код в классе Login (полагаю, это Activity, верно?).

Другая проблема, которую я могу найти:

case 200:
        PrepareLogin doLogin = new PrepareLogin();
        doLogin.execute();
        if (doLogin.getStatus().equals(AsyncTask.Status.FINISHED)) {
             // Redirect to intent?
        }
break;

Ваш doLogin.execute(); не должен быть блокирующим вызовом, поэтому следующий if гарантированно будет ошибочным, поэтому перенаправление никогда не сработает.

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