【问题标题】:Accessing UI component on Activity from the Service class's Thread in Android从 Android 中的 Service 类的 Thread 访问 Activity 上的 UI 组件
【发布时间】:2011-06-13 15:44:18
【问题描述】:

我有一个由 MyService 命名的类,它扩展了下面的 Service。一切都将运行到 我删除了Thread的run方法中的Toast.makeText...这一行。

为什么?以及如何从 Thread 类的 run 方法访问 Activity 组件?

public class MyService extends Service {

@Override
public IBinder onBind(Intent intent) { return null; }

@Override
public void onCreate() {
    Toast.makeText(this, "This msg will be shown", Toast.LENGTH_LONG).show();
    Log.d("Bilgi", "This msg will be shown.");
    super.onCreate();
}

@Override
public void onStart(Intent intent, int startId) {
    Toast.makeText(this, "This msg will be shown", Toast.LENGTH_LONG).show();
    super.onStart(intent, startId);

    timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            try {
                Log.d("This msg will ","be shown"); //if I remove next line 
                Toast.makeText(this, "This msg will NOT be shown", Toast.LENGTH_LONG).show(); 

                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }, 5000, 8000);
}

【问题讨论】:

    标签: android multithreading service android-activity


    【解决方案1】:

    以及如何从 Thread 类的 run 方法访问 Activity 组件?

    你没有。使用MessengerMessage 对象从服务发送到活动的Handler。活动——并且只有活动——可以更新它的小部件,并且只能从主应用程序线程中更新。

    Here is a sample application 展示了这一点。

    【讨论】:

    • 也可以使用extending the binder class的绑定服务吗?当“您的服务只是您自己的应用程序的后台工作人员”时,Android 文档似乎建议使用这种方法而不是使用 Messenger
    • @AST:这将是另一种选择,事件总线也是如此。
    【解决方案2】:

    Don't use Threads - 使用AyncTasks。此外,您不应该通过线程/任务访问 Activity 方法/UI。查看第一个链接,了解 Activity 及其“线程”如何协同工作。

    【讨论】:

    • AsyncTasks 现已弃用:此类在 API 级别 30 中已弃用。请改用标准 java.util.concurrent 或 Kotlin 并发实用程序。
    【解决方案3】:

    我知道的唯一方法是在您的活动中使用广播接收器,它会捕获您的消息并更新 UI 或任何您想要的。

    【讨论】:

      【解决方案4】:

      创建Toast时,传入ApplicationContext,可以通过getApplicationContext()获取

      【讨论】:

      • 你的意思是,将上下文从Activity传递给MyService,并将context.getApplicationContext()作为Toast.makeText(context.getApplicationContext(), "textextexte", Toast.LENGTH_SHORT).show();之类的参数传递给Toast.makeText()方法吗?
      • 不,因为Service是Context的扩展,你可以在Service中调用getApplicationContext(); Toast.makeText(getApplicationContext()..
      • 在 MyService 类的 OnStart 方法中,第一个 Toast.makeText 方法正在工作,但 timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { try { Toast.makeText.......
      【解决方案5】:

      UI 小部件不是线程安全的,因此您无法更新 UI 小部件,除非在 Main(UI) 线程中,在您的情况下,使 Toast 在另一个线程中禁止。

      您可能需要使用Handler 之类的东西,并使用Messenger 将消息发送到在活动UI 线程中创建的处理程序。然后在方法handleMessage(Message msg) 中处理小部件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-01
        • 1970-01-01
        • 2013-01-19
        相关资源
        最近更新 更多