现在我正在努力熟悉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
无法正常运行并自动启动流问题,但这是一个小问题,我认为可以轻松修复。但是,我仍然有兴趣知道我的代码是否有“错误”。
答案 0 :(得分:1)
这样做是否常规?或者我应该将所有代码和方法保存在各自的活动中,还是将它们移动到自己的类中是常规的,并从任何Activity需要它们访问它们?
绝对使用通用软件工程原理和最佳实践。专注并为特定目的服务的设计类。您应该查看新的Architecture Components库。这有一些工具,可以让你创建生命周期感知"类。这些类可以负责处理自己资源的生命周期事件,而不是通过管理资源来污染活动。
<强>注释强>
通常,您不应在活动生命周期之外初始化Activity
类的字段。当您依赖仅在生命周期中的某些时间可用的资源(例如视图)时,这可能会导致问题。在这种情况下,初始化Streaming
对象内联其声明可能不会导致任何问题。最好养成将onCreate()
视为&#34;构造函数&#34;的习惯。并改为在此方法中进行所有初始化。