Индикатор выполнения Android Ожидание Не удается создать обработчик внутри потока, который не вызвал ошибку Looper.prepare()

В моем приложении для Android я копирую некоторые данные из базы данных сервера в локальную базу данных. Это может занять более 15 минут. Для более медленных соединений это значение может быть превышено. Итак, я хочу отобразить индикатор выполнения ожидания.

Код размещен ниже.

refresh.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
final ProgressDialog progressDialog = ProgressDialog.show(login.this, "", "Please wait...");
new Thread() {
public void run() {
try{
mySQLiteAdapter.openToWrite();
mySQLiteAdapter.deleteAll();
radapter.openToWrite();
radapter.deleteAll();
uadapter.openToWrite();
uadapter.deleteAll();
        try
            {
                 HttpClient httpclient = new DefaultHttpClient();
                 HttpPost httppost = new HttpPost("http://xxxxxxxxxxxxxxxxxxxxx");
                 HttpResponse response = httpclient.execute(httppost);
                 HttpEntity entity = response.getEntity();
                  is = entity.getContent();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(
                        is, "iso-8859-1"), 8);
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                }
                is.close();
                json = sb.toString();
            } catch (Exception e) {
            Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG).show();
            }

            try {
                jObj = new JSONObject(json);
                contacts = jObj.getJSONArray("get");
                for(int i = 0; i < contacts.length(); i++){
                JSONObject c = contacts.getJSONObject(i);
                    if(!c.isNull("rname"))// || c.getString("rcode").equals(null))
                    {
                        rname = c.getString("rname");
                        rcode = c.getString("rcode");
                        radapter.insert(rcode, rname);
                    }
                    else
                    {
                        rname = "";
                        rcode = c.getString("rcode");
                        radapter.insert(rcode, rname);
                    }
                }
                Toast.makeText(getBaseContext(), " Ryot BackUp completed", Toast.LENGTH_SHORT).show();

            } catch (JSONException e) {
                Toast.makeText(getBaseContext(), "Error"+e.toString(), Toast.LENGTH_LONG).show();
            }
                   progressDialog.dismiss();
               }
            }.start();
            adapter.deleteAll();
            oadapter.deleteAll();
            e2.setText("Back Up completed");
        }
            catch (Exception e) {
               Log.e("tag", e.getMessage());
               }
                   progressDialog.dismiss();
               }
            }.start();
       }

   });

Когда я запускаю свое приложение, индикатор выполнения отображается только в течение нескольких секунд, и выполняется блок Catch, отображая ошибку logcat как

Логкат:

02-26 14:26:07.151: E/tag(301): Can't create handler inside thread that has not called Looper.prepare()

Может кто-нибудь объяснить, в чем ошибка в моем коде и как ее решить


person Linga    schedule 26.02.2013    source источник
comment
типичный случай попытки доступа к пользовательскому интерфейсу из другого потока. Решение использует асинхронную задачу для фоновых вещей и доступ к пользовательскому интерфейсу в onProgressUpdate и onPostExecute.   -  person njzk2    schedule 26.02.2013


Ответы (2)


Toast.makeText(getBaseContext(), " Ryot BackUp completed", Toast.LENGTH_SHORT).show();

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

Поскольку это трудоемкая работа, я настоятельно рекомендую вам использовать AsyncTask в Android.

Но если вы хотите лишь немного изменить существующий код, попробуйте использовать

context.runOnUiThread(new Runnable() {
  public void run() {
    Toast.makeText(...).show();
  }
});

или обработчик, вы можете взглянуть на Как работает обработчик в Android. Основной пример:

public Handler mHandler = new Handler() {

    public void handleMessage(Message msg) {
           //show toast here
    }
}

protected void startLongRunningOperation() {

    Thread t = new Thread() {
        public void run() {
            //do something here
            //update the result
            mHandler.postDelayed(mUpdateResults, 200);}
            mHandler.post(mUpdateResults);
        }
    };
    t.start();
}
person StarPinkER    schedule 26.02.2013
comment
Где я должен использовать это? только для отображения тостов - person Linga; 26.02.2013

Вместо создания нового потока создайте HandlerThread — http://developer.android.com/reference/android/os/HandlerThread.html

Просто замените «новый поток ()» на «новый HandlerThread («любая строка»)», и он должен работать.

person azertiti    schedule 26.02.2013