我正在尝试构建一个简单的音乐播放器,但在方向更改方面遇到问题。我正在使用处理 MediaPlayer 的服务,以便它在后台播放(即使 Activity 不在前台),例如 Google PlayMusic。该服务绑定(bind)到我独特且单一的 MainActivity。问题是,例如,当方向发生变化时,它会破坏 Activity 和服务(我猜这是预期的行为)。
我不确定如何有效地处理生命周期。当方向发生变化时,它会再次将服务绑定(bind)到 Activity 。我的 MainActivity 使用 ViewPager 和 FragmentPagerAdapter 来处理选项卡并更新我对事件的 View 。
当它再次创建 Activity (从方向更改)时,它再次绑定(bind)服务,执行“加载”,然后尝试更新我的 View ,但由于某些原因,寻呼机适配器中的 fragment 为空。我不知道为什么。理想情况下,我认为我应该在应用程序开始时加载所有轨道一次。我应该在 Activity 还是服务中执行此操作(因为它与服务相关)?
我不确定应该如何处理我的服务、 Activity 和寻呼机适配器的生命周期。
我制作了一个示例应用程序来重现我的错误:
public class MyActivity extends 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!? } } }; } }
.
public class ListFragment extends 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; } }
}
.
public class MyPagerAdapter extends 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; } }
编辑: 我了解按照建议在 list 文件中添加设置的方法:
<activity> android:name=.... android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" </activity>
但是,似乎不推荐。我计划有几种语言和不同的布局,我不认为刷新我所有的观点是最好的方法。
最佳答案
您可以尝试将 configChanges 添加到要在 Activity 中定义的 list 中<>它可能会解决您的问题:
<activity>
android:name=.....
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />
</activity>
如果它不起作用,您可以尝试在您的 Activity 中实现 onConfigurationChanged() 方法。
关于java - MediaPlayer 服务、ViewPagerAdapter 方向更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25648443/