Java 使用侦听器和匿名类--最佳实践?

Java 使用侦听器和匿名类--最佳实践?,java,android,listener,Java,Android,Listener,我目前正在进行我的第三个Android项目的大规模发布。与我目前的应用程序相比,我的前两个应用程序是相对基本的,这是迄今为止我最复杂的工作。因此,我不得不面对比我习惯的更多的听众 具体来说,我的应用程序中涉及在MediaPlayer中播放web流的部分已经使用了三个侦听器 微调器的侦听器: stationSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { String newStreamUrl; @O

我目前正在进行我的第三个Android项目的大规模发布。与我目前的应用程序相比,我的前两个应用程序是相对基本的,这是迄今为止我最复杂的工作。因此,我不得不面对比我习惯的更多的听众

具体来说,我的应用程序中涉及在MediaPlayer中播放web流的部分已经使用了三个侦听器

微调器的侦听器:

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

});
以及当缓冲完成时触发回放的侦听器:

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

            }

        });
    }
}

}
公共类StreamActivity扩展活动{
静态私有媒体播放器;
静电放电;
静态字符串streamUrl=“defaultStreamURL”;//默认值为128kb/s流。
private static final String TAG=StreamActivity.class.getName();//用于日志记录的标记常量
@凌驾
公共布尔onCreateOptions菜单(菜单){
//为菜单充气;这会将项目添加到操作栏(如果存在)。
getMenuInflater().充气(R.menu.stream,menu);
返回true;
}
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.stream_布局);
//构建选择微调器
微调器站微调器=(微调器)findViewById(R.id.station\u微调器);
ArrayAdapter stationAdapter=ArrayAdapter.createFromResource(这个,R.array.station\u string\u数组,android.R.layout.simple\u微调器\u项);
stationAdapter.setDropDownViewResource(android.R.layout.simple\u微调器\u下拉菜单\u项);
stationSpinner.setAdapter(stationAdapter);
//集合微调器决策逻辑
stationSpinner.setOnItemSelectedListener(新的OnItemSelectedListener(){
字符串newstreamur;
@凌驾
已选择公共视图(AdapterView父视图、视图selectedItemView、整型位置、长id){
开关(位置){
//根据用户的选择,更改URL以匹配适当的站点和流质量。
案例0:
//128kb 89.7流
//默认情况下,始终在创建活动时执行。
newstreamur=“defaultStreamUrl”;
changeStream(newstreamur);
打破
案例1:
//320kb流
newstreamur=“URL1”;
changeStream(newstreamur);
打破
案例2:
//128kb流2
newstreamur=“URL2”;
changeStream(newstreamur);
打破
案例3:
//320kb蒸汽2
newstreamur=“URL3”;
changeStream(newstreamur);
}   
}
@凌驾
未选择公共无效(AdapterView父视图){
}
});
//使用默认设置构建音频播放器。
mp=buildAudioPlayer();
}
/**
*生成并返回已配置的、未准备好的MediaPlayer。
*/
公共媒体播放器buildAudioPlayer(){
//构建媒体播放器
mp=新媒体播放器();
试一试{
mp.reset();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.setDataSource(streamUrl);
}捕获(IllegalArgumentException e){
Log.e(标记为“捕获的IllegargumentException:”);
e、 printStackTrace();
}捕获(非法状态){
Log.e(标签,“捕获非法状态异常:”);
e、 printStackTrace();
}捕获(安全异常e){
Log.e(标记“捕获的安全异常:”);
e、 printStackTrace();
}捕获(IOE异常){
Log.e(标记“捕获IOException:”);
e、 printStackTrace();
}
pd=新进度对话框(本);
返回mp;
}
受保护的void changeStream(字符串newstreamur){
streamUrl=newstreamur;
//如果流当前正在播放,则停止流以防止状态异常
if(mp.isPlaying()){
Log.i(标记,“由用户更改的流源。正在重建流”);
Log.i(标记“流播放停止”);
mp.stop();
}
//用新的流URL重建播放器。
mp.reset();
mp=buildAudioPlayer();
}
/**
*停止音频,断开与流的连接,并将媒体播放器返回到未准备好的状态。由按钮onClick事件调用。
*@param v按钮被用户按下。
*/
公共音频(视图v){
mp.stop();
Log.i(标记“流播放停止”);
}
/**
*暂停音频,不更改连接或媒体播放器。由按钮onClick事件调用。
*@param v按钮被用户按下。
*/
公共空间pauseAudio(视图五){
mp.pause();
Log.i(标记“流播放暂停”);
}
/**
*异步准备媒体播放器。缓冲时显示提示,完成后自动启动。
*@param v按钮被用户按下。
*/
公共播放音频(视图五){
//如果暂停,请在不中断的情况下继续播放。
if(mp.isPlaying()){
mp.start();
}否则{
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();

            }

        });
    }
}

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