Java 从doInBackground方法获取回调结果

Java 从doInBackground方法获取回调结果,java,android,callback,Java,Android,Callback,我刚刚开始学习如何创建android应用程序,我想构建速度测试应用程序。为此,我使用了这个类: 我在github网站上遵循了这个示例,但问题是我无法在UI上显示结果。我试图实现类接口,但结果导致了许多错误。有人知道这是可以做到的吗?我只想在我的应用程序的GUI上显示结果 这是我正在使用的代码: public class SpeedTestTask extends AsyncTask<Void, Void, String> { @Override pr

我刚刚开始学习如何创建android应用程序,我想构建速度测试应用程序。为此,我使用了这个类:

我在github网站上遵循了这个示例,但问题是我无法在UI上显示结果。我试图实现类接口,但结果导致了许多错误。有人知道这是可以做到的吗?我只想在我的应用程序的GUI上显示结果

这是我正在使用的代码:

public class SpeedTestTask extends AsyncTask<Void, Void, String> {

        @Override
        protected void onPreExecute() {
            mRunningBar.setVisibility(View.VISIBLE);
        }

        @Override
        protected String doInBackground(Void... params) {

            SpeedTestSocket speedTestSocket = new SpeedTestSocket();
            speedTestSocket.addSpeedTestListener(new ISpeedTestListener() {

                @Override
                public void onDownloadPacketsReceived(int packetSize,
                                                      float transferRateBitPerSeconds,
                                                      float transferRateOctetPerSeconds) {


                    //Log.i(TAG, "download transfer rate  : " + transferRateOctetPerSeconds * 1000 + "MBps");
                    download_result.setText("Download speed  : " + transferRateOctetPerSeconds * 1000 + " MBps");
                }

                @Override
                public void onDownloadError(int errorCode, String message) {
                    Log.i(TAG, "There was error " + errorCode + " Message: " + message);
                }

                @Override
                public void onUploadPacketsReceived(int packetSize,
                                                    float transferRateBitPerSeconds,
                                                    float transferRateOctetPerSeconds) {
                    download_result.setText("Upload speed (upload)  : " + transferRateOctetPerSeconds * 1000 + " MBps");
                }

                @Override
                public void onUploadError(int errorCode, String message) {
                  //  Log.i(TAG, "Upload error " + errorCode + " occured with message : " + message);
                    download_result.setText("Upload error (upload) " + errorCode + " Message: " + message);
                }

                @Override
                public void onDownloadProgress(int percent) {
                }

                @Override
                public void onUploadProgress(int percent) {
                }

            });

           speedTestSocket.startDownload("ipv4.intuxication.testdebit.info", 80,"/fichiers/10Mo.dat");
            speedTestSocket.startUpload("1.testdebit.info",
                    80, "/", 10000000);



            return null;
        }

        @Override
        protected void onPostExecute(String result) {
          //  download_result.setText(result);
            mRunningBar.setVisibility(View.GONE);

        }
    }
公共类SpeedTestTask扩展了AsyncTask{
@凌驾
受保护的void onPreExecute(){
mRunningBar.setVisibility(View.VISIBLE);
}
@凌驾
受保护字符串doInBackground(无效…参数){
SpeedTestSocket SpeedTestSocket=新SpeedTestSocket();
addSpeedTestListener(新的ISpeedTestListener(){
@凌驾
收到下载包的公共无效(int packetSize,
浮点传输速率比特秒,
浮点数传输速率(秒){
//Log.i(标签“下载传输速率:“+transferRateOctetPerSeconds*1000+”MBps”);
下载_result.setText(“下载速度:+transferRateOctetPerSeconds*1000+“MBps”);
}
@凌驾
public void onDownloadError(整数错误代码,字符串消息){
Log.i(标记“有错误”+错误代码+”消息:“+消息);
}
@凌驾
接收到公共无效的OnPloadPackages(整数包大小,
浮点传输速率比特秒,
浮点数传输速率(秒){
下载_result.setText(“上传速度:”+transferRateOctetPerSeconds*1000+“MBps”);
}
@凌驾
public void onUploadError(int-errorCode,字符串消息){
//Log.i(标签,“上传错误”+错误代码+”与消息一起出现:“+消息”;
下载_result.setText(“上传错误(上传)”+错误代码+”消息:“+消息);
}
@凌驾
公共无效onDownloadProgress(整数百分比){
}
@凌驾
公共程序(整数百分比){
}
});
speedTestSocket.startDownload(“ipv4.intuxication.testdebit.info”,80,“/fichiers/10Mo.dat”);
speedTestSocket.startUpload(“1.testdebit.info”,
80, "/", 10000000);
返回null;
}
@凌驾
受保护的void onPostExecute(字符串结果){
//下载_result.setText(result);
mRunningBar.setVisibility(View.GONE);
}
}

您在
doInBackground
中编写的任何内容都将在非UI线程中执行。如果要更新UI元素,则必须在UI线程中执行的
onPostExecute
中执行

编辑

如果必须从任何其他线程更新UI元素,则可以执行以下操作

runOnUiThread(new Runnable() {
     public void run() {
        download_result.setText("Download speed  : " + transferRateOctetPerSeconds * 1000 + " MBps");

     }
});
编辑2


我被纠正了。您还可以像这里提到的一些用户那样使用
onProgressUpdate()
来操作UI元素。我认为使用
onProgressUpdate
将是比我在这里建议的更好的选择

引用AsyncTask文档中有关更新进度指标的内容:

onProgressUpdate(Progress…),在调用publishProgress(Progress…)后在UI线程上调用。执行的时间未定义。此方法用于在后台计算仍在执行时在用户界面中显示任何形式的进度。例如,它可以用于制作进度条动画或在文本字段中显示日志


我认为这将非常适合您的用例。

在doInBackground中提出所有internet请求,并在PostExecute中更新布局ui。所有preExcute、postExcute和onProgress都位于主线程(ui线程)中,您可以在其中更新ui

您可能正在寻找
publishProgress
onProgressUpdate
回调。仅下载的示例:

@Override
public void onDownloadProgress(int percent) {
   SpeedTestTask.this.publishProgress(percent);
}
覆盖
AsyncTask
onProgressUpdate
回调:

@Override
 protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
        // update your Views here
 }
如果您想同时发布下载和上载进度,您需要一种方法让
onProgressUpdate
回调知道正在更新哪种进度。由于它采用的参数是一个数组(
Integer…values
),因此可以为每种特定的进度使用不同的索引。例如:

 @Override
 public void onDownloadProgress(int percent) {
  // using the index 0 for download
  SpeedTestTask.this.publishProgress(percent, -1);
}
其他回拨:

 @Override
 public void onUploadProgress(int percent) {
 // using the index 1 for upload
 SpeedTestTask.this.publishProgress(-1, upload);
}
然后:


编辑:由于我不知道库是否可以将值-1传递给回调函数,因此我以它为例。可能更安全的做法是使用其他常量来指示相应索引中没有值。

不要更新后台线程中的任何UI元素。 AsyncTask:onOpreExecute-->在主线程上运行。doInBackground-->在工作线程上运行。onPostExecute-->在主线程上运行

因为你正在更新

下载_result.setText(“上传错误(上传)”+错误代码+”消息:“+消息)

在doInBackground中,一旦出现异常,应用程序就会崩溃


在主线程中执行此操作。

感谢@MuchOverflow的快速回答。所以我只是把我的代码移到onPostExecute?在你的情况下,我认为这是不可能的,因为你必须做网络操作。请检查我的更新答案
您必须在onPostExecute中进行检查
检查此项谢谢您的评论@Droidman。我尝试了你的代码,但在“onDownloadProgress”和“onUploadProgress”上出错
@Override
protected void onProgressUpdate(Integer... values) {
  super.onProgressUpdate(values);
    if(values[0] != -1)
      // download
    else
      //upload
}