Java Android工作室编码约定&;可能的上下文错误?

Java Android工作室编码约定&;可能的上下文错误?,java,android,android-studio,android-context,Java,Android,Android Studio,Android Context,现在,我正试图更加熟悉Android开发。当然,我正在使用Android Studio来完成这项工作。作为一个项目,我正在编写一个应用程序,用MediaPlayer类处理来自URL的流媒体 我得到了这个函数,并且做了我需要它做的事情。然而,我不希望我的MainActivity被可以存储在它们自己的类中的方法和变量弄得乱七八糟 关于这一点,我有几个问题: 这是常规做法吗?或者我应该将所有代码和方法都保存在它们各自的活动中,还是将它们移动到它们自己的类中,并从任何需要它们的活动中访问它们都是常规做

现在,我正试图更加熟悉Android开发。当然,我正在使用Android Studio来完成这项工作。作为一个项目,我正在编写一个应用程序,用
MediaPlayer
类处理来自URL的流媒体

我得到了这个函数,并且做了我需要它做的事情。然而,我不希望我的MainActivity被可以存储在它们自己的类中的方法和变量弄得乱七八糟

关于这一点,我有几个问题:

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

  • 在将MediaPlayer移动到另一个类时,我在使其正确工作方面遇到问题。我读到我必须在调用该方法时给出方法
    上下文。因此,我使用传递了
    Context
    的对象调用了该方法,如下所示

我对这种发展是相当陌生的,所以提示、好习惯和有用的提示总是受欢迎的

下面是我的
main活动
,它调用我在
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) {

        }
    });}
您将注意到一个
实用程序
类。目前,它只保存一个转换为秒的方法,这样我就可以更新正在播放的MP3当前进度的
TextView

我收到的具体错误是来自
onDrag
方法的
NullPointerException
。我似乎不明白为什么

对不起,如果这是一个重复的,我似乎无法找到这在其他任何地方

编辑我确实稍微更改了我的
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,因此没有加载任何内容,也没有流媒体。这是我找到解决方案的一部分

我的
playbutton
仍然出现问题,无法正常工作,流自动启动,但这是一个小问题,我认为可以很容易地解决。然而,我仍然有兴趣知道我的代码是否有“错误”

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

一定要使用通用软件工程原理和最佳实践。设计专注于特定目的的课程。您应该看看新的体系结构组件库。这些工具允许您创建“生命周期感知”类。这些类可以负责为自己的资源处理生命周期事件,而不是用管理资源来污染活动

评论


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

谢谢!这正是我想知道的。因此,从现在起,我应该将所有字段(MediaPlayer、TextView等)保留在onCreate中?那通常不需要课外课吗?至少在与我的文本视图和按钮交互时?@brettsalyer我通常将视图保存在活动或片段子类中。我能想到的唯一例外是自定义列表适配器类,它也需要使用视图。我没有对MediaPlayer做过任何操作,但我可以看出在另一个类中使用它可能会有什么帮助。关键是要确保你在活动生命周期内工作。