1

我必须开发一个包含按钮的小部件(AppWidget)。当按下按钮时,http 请求完成,如果请求成功,小部件通过 Toast 通知事实。由于http请求可以锁定UI,所以我在一个线程中运行它。一切正常(我可以在我的日志中看到“好吧”),除了 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参数上performRequest,但如果我删除final关键字,就会出错。

谢谢指教。

[编辑]

我以这种方式“解决”了这个问题:

-我声明Toast t为全局变量;

- 在 onReceive 方法中,我用它初始化它Toast.makeText(Context,String,int)

- 当我需要展示它时,我只需调用t.show()

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

4

3 回答 3

2

由于http请求可以锁定UI,所以我在一个线程中运行它。一切正常(我可以在我的登录中查看“好的”),除了 Toast 通知。我究竟做错了什么?

问题是您不能从另一个线程更改 UI。您必须将此消息传递回主线程才能显示您的 Toast。


我该怎么做?

有很多不同的方法可以做到这一点,尝试将 Context 保存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
于 2013-02-27T00:21:25.483 回答
0

更好的是,为什么你没有一个在线程完成其任务后调度消息的处理程序。当您在广播接收器中收到该消息时,只需使用消息并使用 Handler 对象中的 post runnable 方法显示 toast。

因为处理程序将属于您的广播接收器,所以当您为可运行对象调用帖子时,您应该在 UI 线程上运行。

参考

http://developer.android.com/reference/android/os/Handler.html http://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable)

于 2013-02-27T00:28:06.687 回答
-1

最简单的方法是打电话

activity.runOnUiThread(new Runnable() {
  public void run() {
    // launch toast here
  }
});

或者,给定一个特定的小部件:

view.post(new Runnable() {
  public void run() {
    // launch toast here
  }
});
于 2013-02-27T00:34:02.810 回答