Android Studio Coding Convention&可能的上下文错误?

时间:2017-11-15 19:47:34

标签: java android android-studio android-context

现在我正在努力熟悉Android开发。当然,我正在使用Android Studio来执行此操作。作为一个项目,我正在编写一个应用程序来处理来自具有MediaPlayer类的URL的流式传输。

我有这个功能,完全按照我的需要去做。但是,我不希望我的MainActivity混乱使用可以存储在自己的类中的方法和变量。

我对此有几个问题:

  • 这样做是否常规?或者我应该将所有代码和方法保存在各自的活动中,还是将它们移动到自己的类中是常规的,并从任何活动需要它来访问它们?

  • 我在将MediaPlayer移动到另一个类时遇到问题。我读到在调用该方法时我必须给出方法Context。所以我使用传递了Context的对象来调用方法,如下所示。

我对这种发展还很陌生,所以我们总是欢迎提示,良好的习惯和有用的提示。

以下是我的MainActivity调用我在Streaming类中添加的方法:

public class MainActivity extends AppCompatActivity {

    Streaming stream = new Streaming(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    stream.updateSeekBar();
    stream.onPlayClick();
    stream.onDrag();

}

你可以在这里看到我调用的所有方法:

public class Streaming extends AppCompatActivity {

private SeekBar musicSeek;
private TextView currentTime;
private TextView totalTime;
private ImageButton play_pause;
private Handler seekHandler = new Handler();
private MediaPlayer mp = new MediaPlayer();
Context context;
Utilities util = new Utilities();

//Default Constructor
public Streaming(){}
//Contructor
public Streaming(Context context){
    this.context = context;
}
//Method to run the runnable to update the seekbar
public void updateSeekBar(){
    seekHandler.postDelayed(mUpdateTimeTask, 100);
}

public void prepareStreaming() throws IOException {
    mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
    mp.setDataSource("http://tricountynaz.net/media/audio/2017-11-08-The%20Compassion%20of%20the%20Christ.mp3");
    mp.prepare();
}

public void startStreaming(){
    mp.start();
}

public void pauseStreaming(){
    mp.pause();
}

//Runnable to update the seekbar with the current position.
private Runnable mUpdateTimeTask = new Runnable() {
    public void run() {
        int totalDuration = mp.getDuration();
        int currentPosition = (mp.getCurrentPosition());


        //Displaying Total Duration time
        totalTime = (TextView)((Activity)context).findViewById(R.id.totalTime);
        totalTime.setText(util.milliSecondsToTimer(totalDuration));
        // Displaying time completed playing
        currentTime = (TextView)((Activity)context).findViewById(R.id.currentTime);
        currentTime.setText(util.milliSecondsToTimer(currentPosition));
        //Set the bars total duration, based on the song duration (converted to seconds)
        musicSeek = (SeekBar)((Activity)context).findViewById(R.id.music_seek);
        musicSeek.setMax(totalDuration/1000);
        // Updating progress bar
        musicSeek.setProgress(mp.getCurrentPosition()/1000);

        // Running this thread after 100 milliseconds
        seekHandler.postDelayed(this, 100);
    }
};

//What happens when the user interacts with the button
public void onPlayClick (){
    play_pause = (ImageButton)((Activity)context).findViewById(R.id.playButton);
    play_pause.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View view) {
            play_pause.setImageResource(R.drawable.ic_pause_name);

            try {
                prepareStreaming();
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (mp.isPlaying()) {
                pauseStreaming();
                play_pause.setImageResource(R.drawable.ic_play_name);


            } else {
                //mediaPlayer.start();
                startStreaming();
            }
        }
    });
}

//Handles when the user interacts with the seekbar
public void onDrag(){
    musicSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
            if(b) {
                //seeks to the current position of the slider when the user (b) interacts.
                mp.seekTo(i*1000);
                musicSeek.setProgress(i);
            }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });}

您会注意到Utilities课程。目前,这只包含一个转换为秒的方法,因此我可以更新正在流式传输的MP3当前进度的TextView项。

我收到的具体错误是来自NullPointerException方法的onDrag。我似乎无法理解为什么。

很抱歉,如果这是重复的话,我似乎无法在其他任何地方找到它。

编辑我确实改变了我的onDrag方法:

//Handles when the user interacts with the seekbar
public void onDrag(){
    musicSeek = (SeekBar)((Activity)context).findViewById(R.id.music_seek);
    musicSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
            if(b) {
                //seeks to the current position of the slider when the user (b) interacts.
                mp.seekTo(i*1000);
                musicSeek.setProgress(i);
            }
        }

这确实修复了nullPointerException,除了现在我在日志中得到这个错误:

E/MediaPlayerNative: Attempt to call getDuration in wrong state: mPlayer=0x0, mCurrentState=0

编辑2 我想我解决了我的问题。在研究我最近的错误后,我意识到我从未在我的MainActivity中调用我的MediaPlayer,因此没有任何内容被加载而且没有任何流式传输。 Here是我找到解决方案的一部分。

我的playbutton无法正常运行并自动启动流问题,但这是一个小问题,我认为可以轻松修复。但是,我仍然有兴趣知道我的代码是否有“错误”。

1 个答案:

答案 0 :(得分:1)

  

这样做是否常规?或者我应该将所有代码和方法保存在各自的活动中,还是将它们移动到自己的类中是常规的,并从任何Activity需要它们访问它们?

绝对使用通用软件工程原理和最佳实践。专注并为特定目的服务的设计类。您应该查看新的Architecture Components库。这有一些工具,可以让你创建生命周期感知"类。这些类可以负责处理自己资源的生命周期事件,而不是通过管理资源来污染活动。

<强>注释

通常,您不应在活动生命周期之外初始化Activity类的字段。当您依赖仅在生命周期中的某些时间可用的资源(例如视图)时,这可能会导致问题。在这种情况下,初始化Streaming对象内联其声明可能不会导致任何问题。最好养成将onCreate()视为&#34;构造函数&#34;的习惯。并改为在此方法中进行所有初始化。