无法在未调用 Looper.prepare() 的线程内创建处理程序
Posted
技术标签:
【中文标题】无法在未调用 Looper.prepare() 的线程内创建处理程序【英文标题】:Can't create handler inside thread that has not called Looper.prepare() 【发布时间】:2011-09-06 23:57:32 【问题描述】:我收到此错误“”
你能告诉我如何解决它吗?
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();
);
开始付款方式:
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);
【问题讨论】:
请贴出startPayment()方法代码。 【参考方案1】:你应该知道,当你尝试修改你的 UI 时,唯一线程可以做到这一点是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();
【讨论】:
【参考方案2】:我假设您在 startPayment() 方法中创建了一个处理程序。您不能这样做,因为只能在 UI 线程上创建处理程序。只需在您的活动类中创建它即可。
【讨论】:
【参考方案3】:而不是new Thread()
行,尝试给予
this.runOnUiThread(new Runnable()
【讨论】:
【参考方案4】:您无法更改线程中的任何 UI,您可以使用 runOnUIThread
或 AsyncTask
了解有关此 click here 的更多详细信息
【讨论】:
【参考方案5】:我发现大多数线程处理都可以用这样的 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 线程中完成。
【讨论】:
我在“new StartPaymentAsyncTask(this).execute((Void []) null) ”中收到此错误错误 - 构造函数 PaymentActivity.StartPaymentAsyncTask(new View.OnClickListener()) 未定义 是的,this
应该是 YourActivity.this
。我已经更新了代码(我认为应该是 PaymentActivity)
断点 onClick 方法和异步任务的构造函数以查看它们是否正常工作(或添加日志记录)。您是否为进度对话框添加了所有设置?我在上面添加了示例代码。
我已将代码修改为完全工人阶级。如果您使用的是 eclipse,您需要做的就是在默认的 android 应用程序中添加一个带有 id 为“button”的按钮,以使其正常工作。如果你注释掉最后抛出的异常,你会得到“没有问题”的消息
您尝试了整个课程,还是只是将您需要的代码插入到代码中?修改后的代码应该显示一个微调器 2 秒(你看到了吗?),然后在日志中你应该看到 startPayment() 方法中的“我正在假装做事”,然后是错误消息,再次出现在日志中。 【参考方案6】:
试试
final Handler handlerTimer = new Handler(Looper.getMainLooper());
handlerTimer.postDelayed(new Runnable()
public void run()
......
, time_interval);
【讨论】:
以上是关于无法在未调用 Looper.prepare() 的线程内创建处理程序的主要内容,如果未能解决你的问题,请参考以下文章
无法在未调用 Looper.prepare() 的线程内创建处理程序
无法在未调用 Looper.prepare() 的线程内创建处理程序
无法在未调用 Looper.prepare()-Alertdialogbox 的线程内创建处理程序 [重复]
无法在未调用 Looper.prepare() Graphhopper 的线程内创建处理程序