web-dev-qa-db-ja.com

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

UIを変更しようとするとき、それを実行できるonlyスレッドはUiThreadであることを知っておく必要があります。

したがって、別のスレッドでUIを変更する場合は、次のメソッドを使用してみてください: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();
29
Houcine

StartPayment()メソッドでハンドラーを作成するとします。ハンドラーはUIスレッドでのみ作成できるため、これを行うことはできません。アクティビティクラスで作成してください。

3
Vladimir Ivanov

new Thread()行の代わりに、

this.runOnUiThread(new Runnable() {
3
Anju

詳細については、runOnUIThreadまたはAsyncTaskを使用してスレッド内のUIを変更することはできません ここをクリック

1
Niranj Patel

ほとんどのスレッド処理は、次のような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");
    }
}

アプリケーションコンテキストを非同期に渡して、ダイアログを作成できるようにします。

この方法で行うことの利点は、UIで実行されるメソッドと、別のバックグラウンドスレッドで実行されるメソッドが正確にわかることです。メインのUIスレッドが遅延することはなく、小さな非同期タスクへの分離は非常に便利です。

このコードは、startPayment()メソッドがUIで何も実行しないことを想定しており、実行する場合は、それをAsyncTaskのonPostExecuteに移動して、UIスレッドで実行されるようにします。

1
Mark Fisher

試す

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

                              }
                                                 }, time_interval});
1
Jaswant Singh