2013-04-10 67 views
0

我目前正在開發我的第三個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(); 

      } 

     }); 
    } 
} 

} 

回答

1

它雜波您的代碼,因爲你讓他們太長時間。將它們減少到最多兩到三行,它將更具可讀性。例如:

stationSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { 
     @Override 
     public void onItemSelected(AdapterView<?> parentView, 
            View selectedItemView, 
            int position, 
            long id) { 
      changeUrl(position); 
     } 

     @Override 
     public void onNothingSelected(AdapterView<?> parentView) { 
     } 
    }; 

... 

private void changeUrl(int spinnerPosition) { 
    String newStreamUrl; 
    switch (position) { 

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

或者,如果它仍然太長,你可以實現它們作爲非匿名內部類。例如:

stationSpinner.setOnItemSelectedListener(new StationSpinnerListener()); 

... 

private class StationSpinnerListener implements OnItemSelectedListener { 
    @Override 
    public void onItemSelected(AdapterView<?> parentView, 
           View selectedItemView, 
           int position, 
           long id) { 
     String newStreamUrl; 
     switch (position) { 

      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) { 
    } 
} 
+0

感謝您的支持!使用這種方法更具可讀性。 – aerotwelve 2013-04-10 22:29:27