我正在尝试构建一个简单的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>
然而,似乎没有推荐。我计划有几种语言和不同的布局,我认为不是所有的观点都是最好的方法。
答案 0 :(得分:2)
您可以尝试将configChanges添加到您要在活动&lt;&gt;中定义的清单中它可以解决你的问题:
<activity>
android:name=.....
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />
</activity>
如果它不起作用,您可以尝试对您的活动实施 onConfigurationChanged()方法。