如果片段可见,则从Service或BroadcastReceiver更新片段UI

时间:2016-10-09 15:05:07

标签: java android android-fragments broadcastreceiver android-service

TL; DR

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

背景

我在Fragment上有一个toggleButton(名为homeFragment)。它显示停止文本if(toggleButton.isChecked),否则显示开始文本。 此toggleButton启动和停止服务。

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

启动此服务后,toggleButton会显示“停止”文字。 此服务会创建粘滞通知并在此之后调用this.stopSelf。 此通知有一个按钮关闭此通知。 此选项会调用BroadcastReceiver来停止/取消通知。

问题/需求

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

我试过了:

  1. 使用布尔值SharedPref键(比如isServiceRunning)来跟踪服务状态。在onCreate()中,我保存了true布尔值。在onDestoy()中,我保存了false布尔值。 然后,我将onSharedPreferencesChangeListener注册到sharedPrefs(inside fragment),检查isServiceRunning的sharedPrefkey是否已更改。 如果是,则调用toggleButton.setChecked(false);

    此方法很少有效。有时它有效,有时没有任何反应。

  2. 使用LocalBroadcastReceiver,但它有很多错误。就像,can't Instantiate Receiver: no empty method。我试着解决, 但想通了,需要做很多工作。此外,访问另一个类中的Fragment视图只是一团糟,因为你必须给它们片段layout 任何时候都可以null。从View给这个接收器类提供onViewCreated()元素很困难。我尝试过layout + findViewById这样做, 但没有成功/错误。

    这种方法从未奏效,我认为效率不高。

  3. 到处使用static个变量。所以,我创建了一个全局View元素(比如说activeLayout)。 它是privatestatic,因此static方法(切换toggleButton的状态)可以访问片段的布局。 从activeLayout方法为onViewCreated()分配了一个布局。

    现在,如果我从我的static调用此stopNotificationReceiver方法,它可以正常工作(我只检查了两次)。但是,显示了一个新的警告:

      

    警告:不要将Android上下文类放在静态字段中;这是一个内存泄漏(也打破了Instant Run)

    所以,我不能将activeLayout作为static变量,这打破了这个想法。

  4. 如果我做错了,请建议我另类。或者纠正我如何做到这一点。

1 个答案:

答案 0 :(得分:3)

使用广播接收器并在片段中注册

您可以使用ur service

中的以下代码来调用Broadcast reciver
Intent intent = new Intent();
intent.putExtra("extra", cappello); 
intent.setAction("com.my.app");
sendBroadcast(intent);

在Fragment中实现BroadcastReceiver:

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 
  }
} 

并将其注册在Fragment的onResume()中:

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