Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果片段可见,则从服务或BroadcastReceiver更新片段UI_Java_Android_Android Fragments_Broadcastreceiver_Android Service - Fatal编程技术网

Java 如果片段可见,则从服务或BroadcastReceiver更新片段UI

Java 如果片段可见,则从服务或BroadcastReceiver更新片段UI,java,android,android-fragments,broadcastreceiver,android-service,Java,Android,Android Fragments,Broadcastreceiver,Android Service,TL;DR 我需要更新一个片段的UI(toggleButton),当它在运行服务的屏幕上可见时 背景 我在片段(名为homeFragment)上有一个切换按钮。如果(toggleButton.isChecked),则显示停止文本,否则显示开始文本。 此切换按钮启动和停止服务 现在,有两种方法可以停止此服务。一个是再次点击toggleButton(停止服务),另一个是通过服务本身 启动此服务时,toggleButton显示“停止”文本。 此服务创建一个粘性通知,然后调用This.stopSelf。

TL;DR

我需要更新一个片段的UI(toggleButton),当它在运行服务的屏幕上可见时

背景

我在片段(名为homeFragment)上有一个
切换按钮
。如果(toggleButton.isChecked),则显示停止文本
,否则显示开始文本。
此
切换按钮启动和停止服务

现在,有两种方法可以停止此服务。一个是再次点击
toggleButton
(停止服务),另一个是通过服务本身

启动此服务时,
toggleButton
显示“停止”文本。 此服务创建一个粘性通知,然后调用
This.stopSelf
。 此通知具有关闭此通知的按钮。 此选项调用
BroadcastReceiver
停止/取消通知

问题/要求

现在,当服务通过通知按钮关闭时,如果应用程序可见或在前台,我想触发片段上的
toggleButton
,再次显示开始文本。 如果appActivity处于后台/暂停/关闭状态,我不需要处理此问题(我通过在
onCreate()
中检查
sharedPrefs
来处理此问题)

我试过:

  • 使用一个布尔SharedPref键(比如
    isServiceRunning
    ),它跟踪服务状态。在
    onCreate()
    中,我保存了一个
    true
    布尔值。在
    onDestoy()
    中,我保存了一个
    false
    布尔值。 然后,我在SharedPreferencesChangeListener上注册一个
    sharedPrefs(内部片段)
    ,它检查
    isServiceRunning
    的sharedPrefkey是否更改。 如果是,则调用
    toggleButton.setChecked(false)

    这种方法很少奏效。有时有效,有时什么也没发生

  • 使用
    LocalBroadcastReceiver
    ,但它有许多错误。比如,
    无法实例化Receiver:no empty方法
    。我试图解决, 但我发现这需要很多工作。此外,在另一个类中访问片段视图也是一团糟,因为您必须为它们提供片段的
    布局
    
    它可以在任何时间
    null
    。很难从
    onViewCreated()
    中为该接收器类指定一个
    视图
    元素。我尝试通过膨胀
    布局
    +
    findViewById
    来完成此操作, 但没有成功/错误

    这种方法从来都不管用,我认为它效率不高

  • 到处使用
    静态
    变量。因此,我创建了一个全局
    视图
    元素(比如
    activeLayout
    )。 它是
    私有的
    静态的
    ,因此
    静态的
    方法(切换
    切换按钮
    的状态)可以访问片段的布局。
    activeLayout
    onViewCreated()
    方法分配一个布局

    现在,如果我从我的
    stopNotificationReceiver
    调用这个
    static
    方法,它就会工作(我只检查了两次)。但是,新的警告显示:

    警告:不要将Android上下文类放在静态字段中;这是内存泄漏(也会中断即时运行)

    因此,我不能将
    activeLayout
    作为
    static
    变量,这打破了整个想法


  • 如果我做错了,请给我一个选择。或者告诉我怎么做。

    使用广播接收器并将其注册到片段中

    您可以在您的服务中使用以下代码调用广播接收器

    Intent intent = new Intent();
    intent.putExtra("extra", cappello); 
    intent.setAction("com.my.app");
    sendBroadcast(intent);
    
    在片段中实现一个广播接收器:

    private class MyBroadcastReceiver extends BroadcastReceiver {
      @Override
      public void onReceive(Context context, Intent intent) {
        Bundle extras = intent.getExtras();
        String state = extras.getString("extra");
        updateView(state);// update your textView in the main layout 
      }
    } 
    
    并将其注册到片段的onResume()中:

    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("com.my.app");
    receiver = new MyBroadcastReceiver();
    registerReceiver(receiver, intentFilter); 
    

    使用广播接收器并将其注册到片段中

    您可以在您的服务中使用以下代码调用广播接收器

    Intent intent = new Intent();
    intent.putExtra("extra", cappello); 
    intent.setAction("com.my.app");
    sendBroadcast(intent);
    
    在片段中实现一个广播接收器:

    private class MyBroadcastReceiver extends BroadcastReceiver {
      @Override
      public void onReceive(Context context, Intent intent) {
        Bundle extras = intent.getExtras();
        String state = extras.getString("extra");
        updateView(state);// update your textView in the main layout 
      }
    } 
    
    并将其注册到片段的onResume()中:

    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("com.my.app");
    receiver = new MyBroadcastReceiver();
    registerReceiver(receiver, intentFilter); 
    

    onPause()
    中注销如果片段不可见,则不调用broadcastReceiver?或者它被触发,但用户界面的更新被忽略?在
    onPause()
    中注销如果片段不可见,则不调用broadcastReceiver?或者它被触发了,但是用户界面的更新被忽略了?