我目前正在開發我的第三個Android項目以進行批量發佈。與我目前的應用程序相比,我的前兩個是相對基本的,這是迄今爲止我最複雜的工作。因此,我一直不得不面對更多的聽衆,然後我習慣了。使用監聽器和匿名類 - 最佳實踐?
具體來說,我的應用程序中處理MediaPlayer中的網絡流的部分已經使用了三個監聽器。
用於微調甲聽者:
stationSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
String newStreamUrl;
@Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
switch (position) {
// Based on the user's selection, change the URL to match the appropriate station and stream quality.
case 0:
// 128kb 89.7 stream
// Default case, always executed on activity creation.
newStreamUrl = "defaultStreamUrl";
changeStream(newStreamUrl);
break;
case 1:
// 320kb stream
newStreamUrl = "URL1";
changeStream(newStreamUrl);
break;
case 2:
// 128kb Stream 2
newStreamUrl = "URL2";
changeStream(newStreamUrl);
break;
case 3:
// 320kb Steam 2
newStreamUrl = "URL3";
changeStream(newStreamUrl);
}
}
@Override
public void onNothingSelected(AdapterView<?> parentView) {
}
});
用於progressDialog甲聽者:
pd = ProgressDialog.show(this, "Loading...", "Buffering Stream", true, true, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
pd.dismiss();
mp.reset();
}
});
與收聽觸發重放時的緩衝完成時:
mp.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// When the stream is buffered, kill prompt and start playing automatically.
pd.dismiss();
mp.start();
Log.i(TAG, "Stream playback started.");
}
});
.. 。我甚至沒有完成實施聽衆來處理所有可能的情況。
從我目前的知識來看,偵聽器必須匿名定義(如我上面所做的那樣),或者寫成一個獨立的類來實現偵聽器,然後在所需的類中實例化。也許這只是我,但我認爲定義這些匿名混淆了我的代碼,並且掩蓋了活動背後的邏輯。但是,由於我真的只在這個類中使用這些監聽器,因此將它們移動到它們自己的單獨文件似乎是一種浪費,因爲它會消耗我的包的名稱空間。
我想知道最佳做法是什麼樣的情況。是否有一個關於聽衆的定義良好的規則,還是僅僅取決於開發者的偏好?我試圖使這個項目儘可能地接近最佳編碼實踐,因爲我是編寫Android應用程序的新手,所以希望我能從中學到一些東西。有什麼想法嗎?
我的整個上下文如有必要代碼:
public class StreamActivity extends Activity {
static private MediaPlayer mp;
static ProgressDialog pd;
static String streamUrl = "defaultStreamURL"; // Default value is 128kb/s stream.
private static final String TAG = StreamActivity.class.getName(); // Tag constant for logging purposes
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.stream, menu);
return true;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stream_layout);
// Build selection spinner
Spinner stationSpinner = (Spinner)findViewById(R.id.station_spinner);
ArrayAdapter<CharSequence> stationAdapter = ArrayAdapter.createFromResource(this, R.array.station_string_array, android.R.layout.simple_spinner_item);
stationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
stationSpinner.setAdapter(stationAdapter);
// Set spinner decision logic
stationSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
String newStreamUrl;
@Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
switch (position) {
// Based on the user's selection, change the URL to match the appropriate station and stream quality.
case 0:
// 128kb 89.7 stream
// Default case, always executed on activity creation.
newStreamUrl = "defaultStreamUrl";
changeStream(newStreamUrl);
break;
case 1:
// 320kb stream
newStreamUrl = "URL1";
changeStream(newStreamUrl);
break;
case 2:
// 128kb Stream 2
newStreamUrl = "URL2";
changeStream(newStreamUrl);
break;
case 3:
// 320kb Steam 2
newStreamUrl = "URL3";
changeStream(newStreamUrl);
}
}
@Override
public void onNothingSelected(AdapterView<?> parentView) {
}
});
// Build audio player using default settings.
mp = buildAudioPlayer();
}
/**
* Builds and returns a configured, unprepared MediaPlayer.
*/
public MediaPlayer buildAudioPlayer() {
// Build MediaPlayer
mp = new MediaPlayer();
try {
mp.reset();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.setDataSource(streamUrl);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Caught IllegalArgumentException: ");
e.printStackTrace();
} catch (IllegalStateException e) {
Log.e(TAG, "Caught IllegalStateException: ");
e.printStackTrace();
} catch (SecurityException e) {
Log.e(TAG, "Caught SecurityException: ");
e.printStackTrace();
} catch (IOException e) {
Log.e(TAG, "Caught IOException: ");
e.printStackTrace();
}
pd = new ProgressDialog(this);
return mp;
}
protected void changeStream(String newStreamUrl) {
streamUrl = newStreamUrl;
// Stop stream if it is currently playing to prevent state exceptions
if (mp.isPlaying()) {
Log.i(TAG, "Stream source changed by user. Rebuilding stream.");
Log.i(TAG, "Stream playback stopped.");
mp.stop();
}
// Rebuild player with new stream URL.
mp.reset();
mp = buildAudioPlayer();
}
/**
* Stops audio, drops connection to stream, and returns Media Player to an unprepared state. Called by a button onClick event.
* @param v Button pressed by user.
*/
public void stopAudio(View v) {
mp.stop();
Log.i(TAG, "Stream playback stopped.");
}
/**
* Pauses audio with no change to connection or Media Player. Called by a button onClick event.
* @param v Button pressed by user.
*/
public void pauseAudio(View v) {
mp.pause();
Log.i(TAG, "Stream playback paused.");
}
/**
* Prepares Media Player asynchronously. Displays prompt while buffering and automatically starts when finished.
* @param v Button pressed by user.
*/
public void playAudio(View v) {
// If we are paused, resume playback without rebuffering.
if (mp.isPlaying()) {
mp.start();
} else {
// If audio is NOT playing, we need to prepare and buffer.
try {
mp.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// When the stream is buffered, kill prompt and start playing automatically.
pd.dismiss();
mp.start();
Log.i(TAG, "Stream playback started.");
}
});
// Prepares stream without blocking UI Thread
mp.prepareAsync();
} catch (IllegalStateException e) {
Log.e(TAG, "Caught IllegalStateException when preparing: ");
e.printStackTrace();
}
// Stop user input while buffering by displaying ProgressDialog
pd.setCancelable(true);
pd.setCanceledOnTouchOutside(false);
pd = ProgressDialog.show(this, "Loading!", "Buffering...", true, true, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
pd.dismiss();
mp.reset();
}
});
}
}
}
感謝您的支持!使用這種方法更具可讀性。 – aerotwelve 2013-04-10 22:29:27