Не удается создать обработчик внутри потока, который не вызвал Looper.prepare()
Я получаю эту ошибку "Не удается создать обработчик внутри потока, который не вызвал Looper.prepare()"
Можете ли вы сказать мне, как это исправить?
public class PaymentActivity extends BaseActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.payment);
final Button buttonBank = (Button) findViewById(R.id.buttonBank);
buttonBank.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
progressDialog = ProgressDialog.show(PaymentActivity.this, "",
"Redirecting to payment gateway...", true, true);
new Thread() {
public void run() {
try {
startPayment("Bank");
} catch (Exception e) {
alertDialog.setMessage(e.getMessage());
handler.sendEmptyMessage(1);
progressDialog.cancel();
}
}
}.start();
}
});
Метод StartPayment:
private void startPayment(String id) {
Bundle b = getIntent().getExtras();
final Sail sail = b.getParcelable(Constant.SAIL);
final Intent bankIntent = new Intent(this, BankActivity.class);
try {
Reservation reservation = RestService.createReservation(
sail.getId(),
getSharedPreferences(Constant.PREF_NAME_CONTACT, 0));
bankIntent.putExtra(Constant.RESERVATION, reservation);
// <workingWithDB> Storing Reservation info in Database
DBAdapter db = new DBAdapter(this);
db.open();
@SuppressWarnings("unused")
long rowid;
rowid = db.insertRow(sail.getId(), sail.getFrom(),
sail.getTo(), sail.getShip(), sail.getDateFrom().getTime(),
sail.getPrice().toString(), reservation.getId().floatValue());
db.close();
// </workingWithDB>
String html = PaymentService.getRedirectHTML(id, reservation);
bankIntent.putExtra(Constant.BANK, html);
} catch (Exception e) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog alertDialog = builder.create();
alertDialog.setMessage(e.getMessage());
alertDialog.show();
}
startActivity(bankIntent);
}
Ответы
Ответ 1
Вы должны знать, что при попытке изменить свой пользовательский интерфейс поток только, который может это сделать, это UiThread
.
Итак, если вы хотите изменить свой пользовательский интерфейс в другом потоке, попробуйте использовать метод: Activity.runOnUiThread(new Runnable);
Ваш код должен выглядеть примерно так:
new Thread() {
public void run() {
YourActivity.this.runOnUiThread(new Runnable(){
@Override
public void run(){
try {
startPayment("Bank");//Edit,integrate this on the runOnUiThread
} catch (Exception e) {
alertDialog.setMessage(e.getMessage());
handler.sendEmptyMessage(1);
progressDialog.cancel();
}
});
}
}
}.start();
Ответ 2
Я предполагаю, что вы создаете обработчик в методе startPayment(). Вы не можете этого сделать, поскольку обработчики могут быть созданы только в потоке пользовательского интерфейса. Просто создайте его в своем классе активности.
Ответ 3
Вместо строки new Thread()
попробуйте дать
this.runOnUiThread(new Runnable() {
Ответ 4
Вы не можете изменить любой пользовательский интерфейс в потоке, который вы можете использовать runOnUIThread
или AsyncTask
для получения более подробной информации об этом нажмите здесь
Ответ 5
Я обнаружил, что большинство обработки потоков могут быть заменены на AsyncTasks следующим образом:
public class TestStuff extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonBank = (Button) findViewById(R.id.button);
buttonBank.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new StartPaymentAsyncTask(TestStuff.this).execute((Void []) null);
}
});
}
private class StartPaymentAsyncTask extends AsyncTask<Void, Void, String> {
private ProgressDialog dialog;
private final Context context;
public StartPaymentAsyncTask(Context context) {
this.context = context;
}
@Override
protected void onPreExecute() {
dialog = new ProgressDialog(context);
// setup your dialog here
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setMessage(context.getString(R.string.doing_db_work));
dialog.setCancelable(false);
dialog.show();
}
@Override
protected String doInBackground(Void... ignored) {
String returnMessage = null;
try {
startPayment("Bank");
} catch (Exception e) {
returnMessage = e.getMessage();
}
return returnMessage;
}
@Override
protected void onPostExecute(String message) {
dialog.dismiss();
if (message != null) {
// process the error (show alert etc)
Log.e("StartPaymentAsyncTask", String.format("I received an error: %s", message));
} else {
Log.i("StartPaymentAsyncTask", "No problems");
}
}
}
public void startPayment(String string) throws Exception {
SystemClock.sleep(2000); // pause for 2 seconds for dialog
Log.i("PaymentStuff", "I am pretending to do some work");
throw new Exception("Oh dear, database error");
}
}
Я передаю контекст приложения в Async, чтобы он мог создавать из него диалоги.
Преимущество этого способа заключается в том, что вы точно знаете, какие методы выполняются в пользовательском интерфейсе и которые находятся в отдельном фоновом потоке. Ваш основной поток пользовательского интерфейса не задерживается, и разделение на небольшие задачи async довольно приятно.
В коде предполагается, что ваш метод startPayment() ничего не делает с пользовательским интерфейсом, и если это так, переместите его в onPostExecute из AsyncTask, чтобы он выполнялся в потоке пользовательского интерфейса.
Ответ 6
Try
final Handler handlerTimer = new Handler(Looper.getMainLooper());
handlerTimer.postDelayed(new Runnable() {
public void run() {
......
}
}, time_interval});