Android 等待操作,直到片段';将创建用户的视图

Android 等待操作,直到片段';将创建用户的视图,android,transactions,android-fragments,android-service,Android,Transactions,Android Fragments,Android Service,我正在为音乐播放器编程,音乐在后台服务中播放。当用户终止承载3个片段的活动,然后再次重新启动活动时,我会从服务发送一个广播,其中包含有关当前播放歌曲的信息,以及用户添加到会话中的歌曲列表 问题是,每次我想将最后的信息设置到片段中时,都不会发生任何事情,因为它们的创建时间太长,而且广播没有得到应有的处理 我如何让服务或广播等待片段被创建,以便正确处理它们 以下是相关的代码片段: //When the activity binds to the service, refresh the fragme

我正在为音乐播放器编程,音乐在后台
服务中播放。当用户终止承载3个
片段的
活动
,然后再次重新启动
活动
时,我会从
服务
发送一个
广播
,其中包含有关当前播放歌曲的信息,以及用户添加到会话中的歌曲列表

问题是,每次我想将最后的信息设置到
片段中时,都不会发生任何事情,因为它们的创建时间太长,而且
广播
没有得到应有的处理

我如何让
服务
广播
等待片段被创建,以便正确处理它们

以下是相关的代码片段:

//When the activity binds to the service, refresh the fragments
private ServiceConnection conn = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder service) {
        LocalBinder binder = (LocalBinder) service;
        myService = binder.getService();
        myService.setBound(true);
        if(myService.startedOnce) {
            myService.refreshFragments();
        }
        myService.startedOnce = true;
    }
}

//This is the broadcast receiver of the Fragment
//it receives the broadcast too soon, and I can't set the
//Views so they are always empty.
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    if (action.equals(MusicService.REFRESH_ALL)) {
        Song current = intent.getParcelableExtra("song");
        setCurrentSong(current);
    }
}

你不能在碎片里做点什么吗

Song current=null;
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    if (action.equals(MusicService.REFRESH_ALL)) {
        current = intent.getParcelableExtra("song");
    }
}

@Override
public void onResume()
{
    if(current!=null) setCurrentSong(current);
    super.onResume();
}

最简单的方法就是保留信息,直到片段准备好显示它。使用片段的
setArguments()
方法将信息附加到片段中

@Override
public void onReceive() {
   String action = intent.getAction();
   if(action.equals(MusicService.REFRESH_ALL)) {
      // Creating a new Bundle so the Fragment can control its own object
      Bundle args = new Bundle(intent.getExtras()); 
      Fragment fr = getUsingFragment();
      fr.setArguments(fr);
   }
}
然后,在片段的
onCreateView()
中,只需从
getArguments()
中提取参数,并使用这些值构建视图

@Override
public void onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   Bundle args = getArguments();
   if(args != null) {
      // code to set values if arguments are set
   } else {
      // code to set values if arguments are not set
   }
}
另一种方法是使用setter方法,其中片段本身将值放入
setArguments()
的Bundle中。这样,当片段的视图被破坏并且必须重新创建时,只要在为可能的事件设置参数的基础上创建了视图,就可以更新视图

注意:您只能在片段附加到活动之前调用
setArguments()
。但是,您可以通过从
getArguments()
检索对包的引用,然后简单地输入值,来更新通过
setArguments
传入的包。因此,不要从接收方调用
setArguments()
,而是执行以下操作:

public void setCurrentSong(Song extra) {
   Bundle args = getArguments();
   args.putParcable(KEY_MAP, extra);
   if(/* Views are created */) {
      // update and invalidate the views
   }
}
我是怎么修好的 当我使用一项媒体播放服务时,我想从该服务中调出上次听过的歌曲,以便直接播放。这是一个古老的逻辑,但我实际上是围绕它构建代码的。直到苏斯法我撞上它

这种情况正在发生
  • FragmentActivity
    已创建
  • 服务
    启动并绑定到
  • 同时,异步创建
    片段
  • 服务一旦启动
    ,它就会发送一个包含最新信息的
    广播
  • 由于
    服务
    片段
    创建都是异步的,广播将从服务发送,但由于
    片段
    中的
    广播接收器
    甚至还没有初始化,它们将不会接收
    意图
我做了什么来修复它 我不得不使用回调来确保

  • 服务已创建并绑定到
  • 创建的片段和视图已设置
因此,我使用了
ServiceConnection
,准确地说,是
onServiceConnected()
方法。在那里,我得到了保存最后一首歌曲的首选项,然后发送
广播
片段
接收到它,并适当地设置了
视图
。这也有助于改变方向

代码
我的解决方案只是创建自己的回调接口。在ur片段的onCreateView方法的最后,只需调用回调方法,它告诉ur mainactivity创建完成


它对我有用,希望对你也有帮助。

这不起作用。当我在
onResume()
中时,
current
变量为null,这会导致
NPE
,如果我检查null,则不会设置它。这是因为我从
服务
发送
广播
,该服务尚未完成所述
广播
的发送。因此,onReceive在onResume之后收到。根据片段生命周期,所有视图都应该在调用onResume时创建(更确切地说,在调用onReceive时创建)。您能否详细说明从onReceive内部调用setCurrentSong时出现的问题?视图应该存在。我已将所有与片段相关的创建代码移动到
FragmentActivity
onServiceConnection()
,并且只固定了所有操作的顺序。因此,您认为片段的
BroadcastReceiver
首先接收广播,然后移动到
onResume()
的假设在技术上是错误的。我的假设是基于您在代码中的评论,即“它接收广播太快,我无法设置视图,因此它们总是空的。”这表明在创建视图之前调用了onReceive。第一个测试(这里的前两个注释)确实表明onReceive是在onResume之后调用的。是的,但是由于我做错了什么,我的注释也错了;)所以我很抱歉,但我不能接受这个答案,因为其他人可能会尝试实现这个代码,但它可能无法完全工作。嗯,谢谢你解释得很好的答案。我也会尝试你的方法,并再次考虑最佳答案。什么是
getUsingFragment()
?对于v4支持
Fragment
或股票
Fragment
类,该方法不存在。抱歉。我忘了澄清。它不存在。这就是你用来获取片段的任何方法。您可以使用
findFramgentByTag()
或任何检索要更新的片段的方法来替换它。我试图使它更通用,因为有多种方法可以检索片段。实际上,我通过将所有片段创建代码移动到
FragmentActivity
中的
ServiceConnection
内部类,解决了我的问题。信息技术
//This is the code in the FragmentActivity
private ServiceConnection conn = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder service) {
        LocalBinder binder = (LocalBinder) service;
        myService = binder.getService();
        myService.setBound(true);
        if (myService.startedOnce) {
            myService.refreshFragments();
        } else {
            sendLastSavedSong();
        }
        myService.startedOnce = true;
    }

    public void onServiceDisconnected(ComponentName className) {
        myService.setBound(false);
    }
};