MediaPlayer服务,ViewPagerAdapter on Orientation Change

时间:2014-09-03 15:39:06

标签: java android android-service android-orientation android-pageradapter

我正在尝试构建一个简单的MusicPlayer,我在定位更改时遇到了问题。我正在使用一个处理MediaPlayer的服务,因此它在后台播放(即使活动不在前台),如Google PlayMusic。该服务绑定到我独特的单一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扩展了FragmentPagerAdapter {

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

编辑: 我理解按照建议在Manifest文件中添加设置的方法:

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

然而,似乎没有推荐。我计划有几种语言和不同的布局,我认为不是所有的观点都是最好的方法。

1 个答案:

答案 0 :(得分:2)

您可以尝试将configChanges添加到您要在活动&lt;&gt;中定义的清单中它可以解决你的问题:

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

如果它不起作用,您可以尝试对您的活动实施 onConfigurationChanged()方法。