21 Stimmen

Handler kann nicht innerhalb eines Threads erstellt werden, der nicht Looper.prepare() aufgerufen hat

Ich erhalte die Fehlermeldung "Can't create handler inside thread that has not called Looper.prepare()"

Können Sie mir sagen, wie man das beheben kann?

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();
        }

    });

StartZahlungsmethode:

    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);
}

34voto

Houcine Punkte 23601

Sie sollten wissen, dass beim Versuch, Ihre Benutzeroberfläche zu ändern, die sólo Thread, der das tun kann, ist der UiThread .

Wenn Sie also Ihre Benutzeroberfläche in einem anderen Thread ändern wollen, versuchen Sie, die Methode zu verwenden: Activity.runOnUiThread(new Runnable);

Ihr Code sollte folgendermaßen aussehen:

 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();

3voto

Vladimir Ivanov Punkte 42019

Ich gehe davon aus, dass Sie in der Methode startPayment() einen Handler erstellen. Das ist nicht möglich, da Handler nur auf dem UI-Thread erstellt werden können. Erstellen Sie ihn einfach in Ihrer Aktivitätsklasse.

3voto

Anju Punkte 9252

Anstelle von new Thread() Zeile, versuchen Sie es mit

this.runOnUiThread(new Runnable() {

1voto

Niranj Patel Punkte 36031

Sie können keine UI in Threads ändern, die Sie verwenden können runOnUIThread o AsyncTask für weitere Einzelheiten zu diesem Thema hier klicken

1voto

Mark Fisher Punkte 9558

Ich habe festgestellt, dass die meisten Thread-Handling durch AsyncTasks wie diese ersetzt werden kann:

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");
    }
}

Ich übergebe den Anwendungskontext an den Async, damit er daraus Dialoge erstellen kann.

Der Vorteil dieser Vorgehensweise ist, dass Sie genau wissen, welche Methoden in Ihrer Benutzeroberfläche und welche in einem separaten Hintergrund-Thread ausgeführt werden. Ihr Haupt-UI-Thread ist nicht verzögert, und die Trennung in kleine asynchrone Aufgaben ist ganz nett.

Der Code geht davon aus, dass Ihre startPayment()-Methode nichts mit der Benutzeroberfläche zu tun hat, und wenn doch, verschieben Sie sie in die onPostExecute der AsyncTask, damit sie im UI-Thread ausgeführt wird.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X