与听众和匿名课程一起工作 - 最佳实践?

时间:2013-04-10 21:21:12

标签: java android listener

我目前正在开发第三个用于批量发布的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) {
    }

});

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 个答案:

答案 0 :(得分: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) {
    }
}