我正在编写一个应用程序,它将显示当前下载速度,该速度将每秒更新一次。我的Runnable类能够使用值更新UI,但是当我尝试将其放在循环中以便它将连续运行并每秒更新UI TextView时,应用程序现在挂起。
这是我的MainActivity.java:
public class MainActivity extends Activity implements SpeedMeter.TaskRunnableSpeedMeterMethods{
private Thread mSpeedMeterThread;
private Handler mHandler;
private TextView downloadSpeedOutput;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
downloadSpeedOutput = (TextView) findViewById(R.id.speed);
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message inputMessage) {
SpeedMeter speedMeter = (SpeedMeter) inputMessage.obj;
downloadSpeedOutput.setText(Long.toString(speedMeter.getmDownloadSpeedKB()));
}
};
SpeedMeter speedMeter = new SpeedMeter(this);
speedMeter.run();
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, MainActivity.class);
}
@Override
public void setSpeedMeterThread(Thread currentThread) {
mSpeedMeterThread = currentThread;
}
@Override
public void setInternetSpeed(SpeedMeter speedMeter) {
Message completeMessage = mHandler.obtainMessage(1, speedMeter);
completeMessage.sendToTarget();
}
}
这是另一个SpeedMeter.java:
public class SpeedMeter implements Runnable {
final TaskRunnableSpeedMeterMethods mMainActivity;
private long mDownloadSpeedKB;
public SpeedMeter(TaskRunnableSpeedMeterMethods mainActivity) {
mMainActivity = mainActivity;
}
@Override
public void run() {
mMainActivity.setSpeedMeterThread(Thread.currentThread());
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
// while(true) {
long rxBytesPrevious = TrafficStats.getTotalRxBytes();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long rxBytesCurrent = TrafficStats.getTotalRxBytes();
long downloadSpeed = rxBytesCurrent - rxBytesPrevious;
setmDownloadSpeedKB(downloadSpeed/1000);
mMainActivity.setInternetSpeed(this);
// }
}
public long getmDownloadSpeedKB() {
return mDownloadSpeedKB;
}
public void setmDownloadSpeedKB(long mDownloadSpeedKB) {
this.mDownloadSpeedKB = mDownloadSpeedKB;
}
interface TaskRunnableSpeedMeterMethods {
void setSpeedMeterThread(Thread currentThread);
void setInternetSpeed(SpeedMeter speedMeter);
}
}
任何帮助将不胜感激!
答案 0 :(得分:2)
你没有将runnable作为新线程启动,而是像普通函数一样调用run函数(所以你在你的UI线程上执行while循环来阻止它)
替换
speedMeter.run();<br />
SpeedMeter speedMeter = new SpeedMeter(this);
与
new Thread(new SpeedMeter(this)).start();
请参阅https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html了解有关如何启动Runnable的更多信息:)
答案 1 :(得分:2)
执行此操作的理想方法是创建一个AsyncTask
,在doInBackground()
调用中完成任务后,将消息发布到您的UI线程。
您所遵循的界面结构也没有意义,也没有遵循良好的标准。通常,接口用作回调,这基本上就是你正在做的事情。但标准是从OnSomethingChangedListener接口说onSomethingChangedA()或onSomethingChangedB()。
答案 2 :(得分:0)
我认为你的循环总是正确的,所以app更好地创建一个布尔值并使用while(mboolean)
并将它放在你的循环中
if(something){
mboolean=false;
}
您也可以使用CountDownTimer。 例如:
new CountDownTimer(miliseconds,1000)
//if you have download speed and download size you can find miliseconds
@Override
public void onTick(long l) {
//something you want to do every seconds
}
@Override
public void onFinish() {
//something you want to do on finish
}