0

我試圖構建一個簡單的MusicPlayer,並且在定位更改時遇到問題。我使用的是處理MediaPlayer的服務,因此它在後臺播放(即使該活動不在前臺),例如Google PlayMusic。該服務綁定到我獨特的單一MainActivity。問題是,當方向改變時,例如,它破壞了活動和服務(這是我猜測的預期行爲)。媒體播放器服務,ViewPagerAdapter上的方向更改

我不知道如何有效地處理生命週期。當方向改變時,它再次將服務綁定到活動。我的MainActivity使用ViewPager和FragmentPagerAdapter來處理選項卡並更新我對事件的看法。

當它再次創建活動(從方向更改)時,它再次綁定服務,執行「加載」,然後嘗試更新我的視圖,但由於某些原因頁面適配器中的片段爲空。我不知道爲什麼。理想情況下,我認爲我應該在應用程序開始時加載所有曲目。我應該在活動還是服務中這樣做(因爲它與服務有關)?

我不知道如何處理我的服務,活動和尋呼機適配器的生命週期。

我做了我的重現錯誤示例應用程序:

公共類MyActivity延伸活動{

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延伸片段{

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

編輯: 我理解的方式在清單文件中添加設置的建議:

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

但是,它似乎不被推薦。我計劃有幾種語言和不同的佈局,我不認爲刷新我所有的觀點是最好的方法。

回答

2

您可以嘗試對configChanges添加到您的清單在活動<來定義>它可能會解決你的問題:

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

,如果它不工作,你可以嘗試實現onConfigurationChanged()方法到您的活動。

+0

我讀過這個「修復」是一個解決方法,但沒有建議。有很多原因會導致活動重新啓動,例如語言更改。我會有同樣的問題。我計劃處理幾種語言。 http://stackoverflow.com/questions/7818717/why-not-use-always-androidconfigchanges-keyboardhiddenorientation – MiniW 2014-09-03 16:10:27

+0

@MiniW,好吧!你可以添加到android:configChanges =「locale」來處理語言change.i認爲這種追求可能會有所幫助:http://stackoverflow.com/questions/2644377/changing-locale-force-activity-to-reload-resources – AaoIi 2014-09-03 16:28:11

+0

如果我有不同的佈局,我應該如何處理它?我想這是在onConfigurationChanged(),但我不知道如何有效地處理它。 – MiniW 2014-09-03 16:39:48

相關問題