从线程在窗口小部件中显示Toast

时间:2013-02-27 00:16:32

标签: android multithreading android-appwidget

我要开发一个包含按钮的小部件(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)

我希望有更好的解决方案。

3 个答案:

答案 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
  }
});