【问题标题】:android - calling ui thread from worker threadandroid - 从工作线程调用ui线程
【发布时间】:2012-11-24 16:16:42
【问题描述】:

您好,我想让Toast 对我可用,无论何时我都可以在我的应用程序中使用任何线程。所以为此我扩展了Activity 类:

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.Toast;

public class MyActivity extends Activity{
    private Handler mHandler;

    @Override   
    public void onCreate(Bundle savedInstanceState) {       
        mHandler = new Handler();
        super.onCreate(savedInstanceState);
    }

    private class ToastRunnable implements Runnable {
        String mText;

        public ToastRunnable(String text) {
            mText = text;
        }

        public void run(){
           Toast.makeText(getApplicationContext(), mText, Toast.LENGTH_SHORT).show();
        }
    }

    public void doToast(String msg) {
        mHandler.post(new ToastRunnable(msg));
    }
}

所以我的应用程序中的所有 Activity 类现在很简单

public class AppMain extends MyActivity {
   //blah
}

我期望能够(在工作线程中)做的是:

try{
   MyActivity me = (MyActivity) Looper.getMainLooper().getThread();
   me.doToast("Hello World");
}
catch (Exception ex){
   Log.e("oh dear", ex.getMessage());
}

只要Activity 是“MyActivity”,它应该可以工作 - 但问题是 ---> Looper.getMainLooper().getThread(); 没有将MyActivity 返回给我,这让我哭了 -我究竟做错了什么?

:编辑:

一些背景来解释“为什么”我坚持这种类型的实现。

我需要能够向用户确认“HTTP POST”事件已成功。现在。如果用户在 UI 表单上单击“确定”,那么它当时可能或可能没有互联网。如果它有互联网 - 一切都很好 - 它通过 HTTP POST 发布表单一切都很好.. 但如果大多数情况下 没有互联网(99.999% 的 Android 应用程序在这方面蹩脚/可怜/哀嚎,并且基本上不向用户提供 plan "b" 假设在任何时候都有互联网 - 当它不存在时)

我的应用不会“跛脚(我这么称呼它)”——它确实有一个计划“b”,而是“排队”发布事件并每 x 分钟重试一次。现在这个是后台的静默线程。我在整个应用程序中都有大量的用户交互我不知道用户将“在哪里”,但最终当队列/重试/队列/重试的 HTTP POST 返回“!成功! " 我想 Toast 将其作为给用户的消息(例如:“您的表单已发送”)

【问题讨论】:

    标签: android android-activity toast ui-thread


    【解决方案1】:

    runOnUiThread 有什么问题?

    http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)

    activity.runOnUiThread(new Runnable() {
        public void run() {
            Toast.makeText(activity, "Hello, world!", Toast.LENGTH_SHORT).show();
        }
    });
    

    【讨论】:

    • 不,我想向用户发布 Toast 消息,runOnUiThread 接受 Runnable ActionToast 不兼容
    • 为什么不使用getApplicationContext()
    • 无关紧要但不真实。 总是有一个应用程序上下文。你是否能做到是另一回事。
    • 那么为什么不使用 BroadcastReceiver 并让您的 MyActivity 实现监听它呢?
    • @Rawkode 我发现这篇文章helloandroid.com/tutorials/broadcast-receiver-activity 基本上可以完成我需要的工作......简单,优雅
    【解决方案2】:

    使用下面的代码。创建包含您的活动实例的活动对象..

    activity.runOnUiThread(new Runnable() {
      public void run() {
        Toast.makeText(activity.getApplicationContext(),"Toast text",Toast.LENGTH_SHORT).show();
      }
    );
    

    【讨论】:

    • 我在一个worker 线程中没有activity (它不能作为参数传递,因为工作人员一直在尝试连接到服务器以发送消息.. 和活动调用然后自行关闭。我需要从服务器确认并在事件发生后立即向用户确认事件。我所需要的只是 Android 将当前的 ui 线程作为 Activity 咳出。
    • 如果您无法将活动引用传递给工作线程,那么很明显您的线程设计是问题的根源。您应该能够在创建线程时传递引用,而不是暗示线程自己实现。
    【解决方案3】:

    您不能只将getThread() 的结果转换为MyActivity 基类的实例。 getThread() 返回一个与Activity 无关的Thread

    没有很好的——阅读:干净——做你想做的事的方式。在某些时候,您的“工作线程”抽象必须引用可以为您创建Toast 的东西。保存一些包含对您的Activity 子类的引用的静态变量只是为了能够快捷地创建Toast,这是导致内存泄漏和痛苦的秘诀。

    【讨论】:

    • 我没有使用静态类,它是Activity 的基础扩展,包含Handler.. 我想要Android 做的就是咳出当前活动..
    • @conners:这并没有改变getThread()返回Thread的事实,这不是Activity,更不用说MyActivity了。
    • 我同意,但必须有办法,就 Android 允许我在 SDK 中使用 Activity 是 UI 线程的正面。我不知道为什么没有Looper.getMainLooper().getThread().getActivity() / .getContext() 说实话.. 我期待会有一个。大多数解决方案都要求您将上下文作为参数传递 - 但是如果您不知道它是什么上下文,或者如果它是调用工作人员的表单关闭事件(如我的情况)怎么办?
    • 我不知道什么是“表单关闭事件”。上下文管理是 Android 开发的重要组成部分,将其短路几乎总是不明智的。您的问题归结为确定如何在您需要的地方获取适当的Context 对象。
    • 根据您的修改,您可能会使用AsyncTask 来执行“无限重试”例程,并在onPostExecute() 中显示您的Toast。或ServiceBroadcastReceiver。原始的Thread 不是解决问题的最佳方法。
    【解决方案4】:

    如果是在您自己的活动中,为什么不能直接致电doToast()

    【讨论】:

      【解决方案5】:

      你为什么不发送一个由广播接收器捕获的意图,然后广播接收器可以在通知托盘中创建一个通知。这不是祝酒,而是通知用户他的帖子已成功的一种方式。

      【讨论】:

        【解决方案6】:

        这将允许您显示消息,而无需依赖上下文来启动 toast,仅在显示消息本身时引用。

        runOnUiThread 无法从 OpenGL 视图线程工作,这就是解决方案。希望对您有所帮助。

        private Handler handler = new Handler();
        handler.post(new Runnable() {
            public void run() {
                Toast.makeText(activity, "Hello, world!", Toast.LENGTH_SHORT).show();
            }
        });
        

        【讨论】:

          【解决方案7】:

          如果你有上下文,你可以像这样从非活动类调用 ui 线程。

          ((Activity)context).runOnUiThread(new Runnable() {
              public void run() {
                  // things need to work on ui thread
              }
          });
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-01-24
            • 1970-01-01
            相关资源
            最近更新 更多