web-dev-qa-db-fra.com

Impossible de créer un gestionnaire dans le thread qui n'a pas appelé Looper.prepare ()

Je reçois cette erreur "Impossible de créer un gestionnaire dans le thread qui n'a pas appelé Looper.prepare ()" 

Pouvez-vous me dire comment résoudre ce problème? 

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

    });

Méthode de 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);
}
17
Sergio

Vous devriez savoir que lorsque vous essayez de modifier votre interface utilisateur, le thread only qui peut le faire est la UiThread.

Donc, si vous voulez modifier votre interface utilisateur dans un autre thread, essayez d'utiliser la méthode: Activity.runOnUiThread(new Runnable);

Votre code devrait être comme ça: 

 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

Je suppose que vous créez un gestionnaire dans la méthode startPayment (). Vous ne pouvez pas faire cela, car les gestionnaires peuvent être créés uniquement sur le fil de l'interface utilisateur. Créez-le simplement dans votre classe d'activité.

3
Vladimir Ivanov

Au lieu de la ligne new Thread(), essayez de donner 

this.runOnUiThread(new Runnable() {
3
Mathew

vous ne pouvez changer aucune interface utilisateur dans le fil que vous pouvez utiliser runOnUIThread ou AsyncTask pour plus de détails à ce sujet cliquez ici

1
Niranj Patel

J'ai trouvé que la plupart des traitements de threads peuvent être remplacés par des tâches asynchrones comme ceci:

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

Je passe le contexte d'application à Async pour qu'il puisse créer des boîtes de dialogue à partir de celui-ci.

L'avantage de le faire de cette façon est que vous savez exactement quelles méthodes sont exécutées dans votre interface utilisateur et lesquelles sont dans un thread d'arrière-plan séparé. Votre thread principal de l'interface utilisateur n'est pas en retard, et la séparation en petites tâches asynchrones est plutôt agréable.

Le code suppose que votre méthode startPayment () ne fait rien avec l'interface utilisateur. Si c'est le cas, déplacez-la dans onPostExecute de la tâche AsyncTask afin qu'elle soit effectuée dans le fil de l'interface utilisateur.

1
Mark Fisher

Essayer

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

                              }
                                                 }, time_interval});
1
Jaswant Singh