MediaPlayer服务,方向更改时的ViewPagerAdapter



我正在尝试构建一个简单的MusicPlayer,但在方向更改方面遇到了问题。我正在使用一个处理MediaPlayer的服务,以便它在后台播放(即使"活动"不在前台),就像谷歌播放音乐一样。该服务绑定到我唯一的MainActivity。问题是,例如,当方向发生变化时,它会破坏活动和服务(我想这是预期的行为)。

我不知道如何有效地处理生命周期。当方向发生变化时,它会再次将服务绑定到活动。我的MainActivity使用ViewPager和FragmentPagerAdapter来处理选项卡并更新我对事件的视图。

当它再次创建活动(从方向更改)时,它会再次绑定服务,执行"加载",然后尝试更新我的视图,但由于某些原因,寻呼机适配器中的片段为空。我不知道为什么。理想情况下,我认为我应该在应用程序开始时加载所有曲目一次。我应该在"活动"或服务中这样做吗(因为它与服务有关)?

我不确定我应该如何处理我的服务、活动和寻呼机适配器的生命周期。

我制作了一个示例应用程序来重现我的错误:

公共类MyActivity扩展Activity{

private MediaPlayerService mediaPlayerService;
private BroadcastReceiver broadcastReceiver;
private MyPagerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);
    ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
    adapter = new MyPagerAdapter(getFragmentManager());
    viewPager.setAdapter(adapter);
    broadcastReceiver = buildBroadcastReceiver();
    Intent intent = new Intent(this, MediaPlayerService.class);
    bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
    if ( serviceBound ) {
        unbindService(connection);
        serviceBound = false;
    }
    super.onDestroy();
}
@Override
protected void onResume() {
    registerReceiver(broadcastReceiver, new IntentFilter(MediaPlayerService.BROADCAST));
    super.onResume();
}
@Override
protected void onPause() {
    unregisterReceiver(broadcastReceiver);
    super.onPause();
}
private boolean serviceBound = false;
private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        mediaPlayerService = ((MediaPlayerServiceBinder) iBinder).getService();
        serviceBound = true;
        mediaPlayerService.load();
    }
    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        serviceBound = false;
    }
};
private BroadcastReceiver buildBroadcastReceiver() {
    return new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            int action = intent.getIntExtra(MediaPlayerService.ACTION, 0);
            if ( action == MediaPlayerService.ACTION_UPDATE_PLAYLIST ) {
                List<String> cities = Arrays.asList("New York", "Toronto", "Tokyo"); //Data would be load from Database here
                ListFragment fragment = adapter.getFragment();
                fragment.updatePlayList(cities); // Fragment is NULL on Orientation changes!?
            }
        }
    };
} }

公共类ListFragment扩展Fragment{

private ArrayAdapter<String> adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View inflatedView = inflater.inflate(R.layout.playlist, container, false);
    adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, new ArrayList<String>());
    ListView listView = (ListView) inflatedView.findViewById(R.id.list_view);
    listView.setAdapter(adapter);
    return inflatedView;
}
public void updatePlayList(List<String> items) {
    adapter.clear();
    adapter.addAll(items);
    adapter.notifyDataSetChanged();
}
}

public class MediaPlayerService extends Service {
public static final String BROADCAST = "example.com.mediaplayersample.Broadcast";
public static final int ACTION_UPDATE_PLAYLIST = 3;
public static final String ACTION = "ACTION";
private MediaPlayer mediaPlayer;
public void load() {
    //Load...
    Intent intent = new Intent(MediaPlayerService.BROADCAST);
    intent.putExtra(MediaPlayerService.ACTION, ACTION_UPDATE_PLAYLIST);
    sendBroadcast(intent);
}
@Override
public IBinder onBind(Intent intent) {
    return new MediaPlayerServiceBinder();
}
public class MediaPlayerServiceBinder extends Binder {
    public MediaPlayerService getService() {
        return MediaPlayerService.this;
    }
}

}

公共类MyPagerAdapter扩展FragmentPagerAdaper{

private ListFragment listFragment;
public MyPagerAdapter(FragmentManager fragmentManager) { super(fragmentManager); };
@Override
public Fragment getItem(int i) {
    if (i == 0) {
        if (listFragment == null) {
            listFragment = new ListFragment();
            return listFragment;
        }
    }
    throw new IllegalStateException("Wrong index " + i);
}
@Override
public int getCount() {
    return 1;
}
public ListFragment getFragment() {
    return listFragment;
} }

编辑:我理解在清单文件中添加设置的建议方法:

<activity> 
  android:name=....
  android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" 
</activity>

然而,它似乎没有被重新推荐。我计划使用几种语言和不同的布局,但我不认为刷新所有视图是最好的方法。

您可以尝试将configChanges添加到要在活动中定义的清单中<>它可能会解决你的问题:

<activity>
android:name=.....
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />
</activity>

如果它不起作用,您可以尝试将onConfigurationChanged()方法实现到您的活动中。

相关内容

  • 没有找到相关文章

最新更新