Can't create handler inside thread that has not called Looper.prepare()

前端 未结 6 1728
我寻月下人不归
我寻月下人不归 2020-12-03 16:50

I get this error \"Can\'t create handler inside thread that has not called Looper.prepare()\"

Can you tell me how to fix it?

public class PaymentAc         


        
6条回答
  •  Happy的楠姐
    2020-12-03 17:54

    I've found that most thread handling can be replaced by AsyncTasks like this:

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

    I pass in the Application Context to the Async so it can create dialogs from it.

    The advantage of doing it this way is you know exactly which methods are run in your UI and which are in a separate background thread. Your main UI thread isn't delayed, and the separation into small async tasks is quite nice.

    The code assumes your startPayment() method does nothing with the UI, and if it does, move it into the onPostExecute of the AsyncTask so it's done in the UI thread.

提交回复
热议问题