我正在开发一个应用程序,其中我得到一个例外,我知道这个是我正在做的愚蠢或小错误但是你的帮助可能会让我抓住并度过我的一天:
public class Demo extends Activity
{
Button btnDemo;
Thread t;
AlertDialog alertDialog;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo);
btnDemo = (Button) findViewById(R.id.btnDemo);
btnDemo.setOnClickListener(new OnClickListener() {
public void onClick(final View v) {
t=new Thread() {
public void run() {
tryDemo();
}
};
t.start();
}
});
}
public void tryDemo()
{
try
{
int i = 5;
if(i == 0 || i == 1)
{
Intent intent_success = new Intent(getApplicationContext(), Main_Activity.class);
startActivity(intent_success);
}
else
{
alertDialog = new AlertDialog.Builder(getApplicationContext()).create();
alertDialog.setTitle("Demo");
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//here you can add functions
} });
alertDialog.setIcon(R.drawable.icon);
alertDialog.setMessage("Sorry!! Either Username or Password Invalid");
alertDialog.show();
}
}
catch(Exception e)
{
Log.i("Demo", "Demo - Demo Exception");
}
}
}
在上面的代码中,如果我在tryDemo函数中使i = 0或i = 1,那么它运行成功,但是如果我使它不是0或1那么它会抛出异常为“Demo - Demo Exception “即可。
我不确定,但我认为异常是从 getApplicationContext() 引起的。
更新: - 1
我得到的例外情况如下:
更新: - 2 如果我删除“线程”部分并在按钮单击事件中写入整个功能代码并用v.getContext()替换“getApplicationContext()”然后它成功运行.........但我想要在THREAD中实现它。
请帮帮我,把我赶出去......
感谢名单
答案 0 :(得分:1)
您可能正在获得RuntimeException
。我尝试在一个不是UI线程的线程中调用一些对话框创建,并得到了这个:
09-09 00:46:37.702: ERROR/AndroidRuntime(763): Uncaught handler: thread Thread-10 exiting due to uncaught exception
09-09 00:46:37.724: ERROR/AndroidRuntime(763): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
09-09 00:46:37.724: ERROR/AndroidRuntime(763): at android.os.Handler.<init>(Handler.java:121)
09-09 00:46:37.724: ERROR/AndroidRuntime(763): at android.view.ViewRoot.<init>(ViewRoot.java:192)
09-09 00:46:37.724: ERROR/AndroidRuntime(763): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
09-09 00:46:37.724: ERROR/AndroidRuntime(763): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
09-09 00:46:37.724: ERROR/AndroidRuntime(763): at android.view.Window$LocalWindowManager.addView(Window.java:392)
09-09 00:46:37.724: ERROR/AndroidRuntime(763): at android.app.Dialog.show(Dialog.java:231)
09-09 00:46:37.724: ERROR/AndroidRuntime(763): at com.pkg.name.ToplistActivity$3.run(ToplistActivity.java:149)
解决方案是将你的else语句包装成:
else {
runOnUiThread(new Runnable() {
public void run() {
...
}
});
}
答案 1 :(得分:1)
只需阅读您的日志:D您尚未调用Looper.prepare()
如果我是正确的,你应该使用Looper.prepare()和Looper.loop()
包装你的AlertDialog代码。所以看起来像:
Looper.prepare()
// AlertDialog code
Looper.loop()
答案 2 :(得分:1)
此帖子中的结帐评论:
Using Application context everywhere?
另外,如果用actiivtyname.getApplicationContext()替换getApplicationContext(),你会得到什么错误?
答案 3 :(得分:1)
这有点不对劲。 首先,您永远不会,从您创建的任何线程中触摸任何UI元素。
你需要使用线程处理程序进行aquatinted: http://developer.android.com/reference/android/os/Handler.html
它们的工作方式是,在普通的UI线程中初始化它们。 (调用onCreate()方法的线程。) 处理程序,是您扩展以在线程之间进行通信的线程安全对象。
所以,在onCreate()上:
Handler pHandler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
Bundle bundle = msg.getData();
int msg_type = bundle.getInt("TYPE");
if (msg_type == MyThread.ERROR_MSG)
{
///SOMETHING HAPPENED
return;
}
else
{
//background task finished ok
}
}
};
然后,从run()方法中,使用Bundle和Message对象向其发送消息。 http://developer.android.com/reference/android/os/Bundle.html和 http://developer.android.com/reference/android/os/Message.html
我喜欢这样做,保持干净是扩展Thread类以增加一点点的一致性......
class MyThead extends Thread
{
public final int ERROR_MSG = 0;
public final int OK_MSG = 1;
Handler mHandler;
MyThread(Handler pHandler)
{
mHandler = pHandler;
}
@Override
public void run()
{
//send a message back to the ui thread....
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putInt("TYPE", OK_MSG);
msg.setData(bundle);
mHandler.sendMessage(msg);
}
}
如果您想要有点花哨,可以完全分离UI代码和工作线程代码。 如果你的后台任务不会花费很长时间,你可以像前面描述的那样使用runonUiThread()。
您可能还想使用AsyncTask,请参阅:http://developer.android.com/reference/android/os/AsyncTask.html
以下是其页面中的示例,其用法相当简单:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
但最终,如果用户在您的任务运行时更改方向,这些方法并不完美。 (或者如果您的活动因任何其他原因被杀死。) 在这种情况下,您需要设置服务:http://developer.android.com/reference/android/app/Service.html