我要开发一个包含按钮的小部件(AppWidget)。 按下按钮时,http请求完成,如果请求成功,则小部件通过Toast通知事实。 由于http请求可以锁定UI,我在一个线程中运行它。 一切正常(我的logat中可以看到“ All right ”),除了Toast通知。 我做错了什么?
在AppWidgetProvider子类中:
@Override
public void onReceive(Context c, Intent intent){
super.onReceive(c, intent);
if(intent.getAction().equals(CLICK_ACTION)){
performRequest(c);
}
}
(我认为问题不需要onUpdate方法)
private void performRequest(final Context c){
new Thread(new Runnable(){
public void run() {
try {
if(Http.get(URL).contains(SUCCESS)){
Toast.makeText(c, "All right", Toast.LENGTH_SHORT).show();
Log.i("Widget","All right");
}
} catch (Exception e) {
e.printStackTrace();
}}}).start();
}
我认为问题是Context
的{{1}}参数,但如果删除performRequest
关键字,则会出错。
感谢您的建议。
[编辑]
我以这种方式解决了这个问题:
-I将final
声明为全局变量;
- 在onReceive方法中,我用Toast t
- 当我需要展示时,我只需拨打Toast.makeText(Context,String,int)
我希望有更好的解决方案。
答案 0 :(得分:2)
由于http请求可以锁定UI,我在一个线程中运行它。一切正常(我可以在我的logat中查看“All right”),Toast通知除外。我做错了什么?
问题是你不能从另一个线程改变UI。您必须将此消息传递回主线程才能显示您的Toast。
我该怎么做?
有很多不同的方法可以做到这一点,尝试将onReceive()
中的上下文保存为字段变量:
Context context;
@Override
public void onReceive(Context c, Intent intent){
super.onReceive(c, intent);
context = c;
...
接下来在您的Activity中创建一个简单的方法:
public void httpGetSucceeded() {
Toast.makeText(context, "All right", Toast.LENGTH_SHORT).show();
Log.i("Widget","All right");
}
现在在Runnable中调用它:
try {
if(Http.get(URL).contains(SUCCESS)){
httpGetSucceeded();
}
} //etc
答案 1 :(得分:0)
更好的是,为什么没有一个处理程序在线程完成其任务后调度消息。当您在广播接收器中收到该消息时,只需使用消息并使用Handler对象中的post runnable方法显示toast。
因为处理程序属于你的广播接收器,所以当你为runnable调用post时,你应该在UI线程上运行。
http://developer.android.com/reference/android/os/Handler.html http://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable)
答案 2 :(得分:-1)
最简单的方法是致电
activity.runOnUiThread(new Runnable() {
public void run() {
// launch toast here
}
});
或者,给定一个特定的小部件:
view.post(new Runnable() {
public void run() {
// launch toast here
}
});