web-dev-qa-db-de.com

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

Ich erhalte diesen Fehler "Handler kann nicht in Thread erstellt werden, der nicht Looper.prepare () aufgerufen hat" 

Kannst du mir sagen, wie ich es reparieren 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();
        }

    });

StartPayment-Methode:

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

Sie sollten wissen, dass wenn Sie versuchen, Ihre Benutzeroberfläche zu ändern, der only - Thread, der dies tun kann, die UiThread ist.

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

Ihr Code sollte so 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();
29
Houcine

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

3
Vladimir Ivanov

Versuchen Sie, anstelle von new Thread() zu geben 

this.runOnUiThread(new Runnable() {
3
Mathew

sie können keine Benutzeroberfläche in Thread ändern. Sie können runOnUIThread oder AsyncTask verwenden, um weitere Informationen zu diesem Thema zu erhalten klicken Sie hier

1
Niranj Patel

Ich habe festgestellt, dass die meisten Thread-Aktionen wie folgt durch AsyncTasks ersetzt werden können:

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 Dialoge erstellt werden können.

Dies hat den Vorteil, dass Sie genau wissen, welche Methoden in Ihrer Benutzeroberfläche ausgeführt werden und welche sich in einem separaten Hintergrundthread befinden. Ihr Haupt-UI-Thread wird nicht verzögert, und die Trennung in kleine asynchrone Aufgaben ist ziemlich schön.

Der Code geht davon aus, dass Ihre startPayment () -Methode nichts mit der Benutzeroberfläche tut. Wenn dies der Fall ist, verschieben Sie sie in die onPostExecute-Datei der AsyncTask, sodass dies im UI-Thread erfolgt.

1
Mark Fisher

Versuchen

final Handler handlerTimer = new Handler(Looper.getMainLooper());
        handlerTimer.postDelayed(new Runnable() {
            public void run() {
                                ...... 

                              }
                                                 }, time_interval});
1
Jaswant Singh