Android AsyncTask第一次执行时花费的时间太长

Android AsyncTask第一次执行时花费的时间太长,android,android-asynctask,Android,Android Asynctask,Asynctask第一次执行需要30秒或更长时间。它发生在我进入活动时。之后,后续调用的异步任务(当我从先前的活动再次进入活动)只花费4或5秒,我认为是“可接受的”。p> 下面是我执行AsyncTask的代码 @Override public void onLocationChanged(Location location) { if (location!=null) { mlastLocation=location;

Asynctask第一次执行需要30秒或更长时间。它发生在我进入活动时。之后,后续调用的异步任务(当我从先前的活动再次进入活动)只花费4或5秒,我认为是“可接受的”。p> 下面是我执行AsyncTask的代码

  @Override
    public void onLocationChanged(Location location) {

        if (location!=null) {
            mlastLocation=location;

            double latitud=Double.parseDouble(getIntent().getStringExtra("latitud").replace("Latitud:", ""));
            double longitud=Double.parseDouble(getIntent().getStringExtra("longitud").replace("Longitud:", ""));
            LatLng origen= new LatLng(latitud,longitud);
            LatLng destino=new LatLng(mlastLocation.getLatitude(),mlastLocation.getLongitude());
            if (mCount==0) {
                FillVariablesAsyncTask tareaAsincrona = new FillVariablesAsyncTask();
                tareaAsincrona.execute(origen, destino);

                mCount++;
            }

        }
    }
这里是AsyncTask的代码,其中onPostExecute更新成员变量并更新UI

 private class FillVariablesAsyncTask extends AsyncTask<LatLng,Void,Document>{


              @Override
        protected Document doInBackground(LatLng... params) {
                  md=new GMapV2Direction();
                  LatLng origen=new LatLng(params[0].latitude,params[0].longitude);
                  LatLng destino=new LatLng(params[1].latitude,params[1].longitude);
                  Document doc = md.getDocument(origen, destino, GMapV2Direction.MODE_WALKING);
                  /*mUbicacionActual = md.getStartAddress(doc);
                  mDuration=md.getDurationText(doc);
                  mDistancia=md.getDistanceText(doc);*/
                  return doc;
        }

        @Override
        protected void onPostExecute(Document doc) {
            super.onPostExecute(doc);
            mUbicacionActual = md.getStartAddress(doc);
            mDuration=md.getDurationText(doc);
            mDistancia=md.getDistanceText(doc);
            if (mUbicacionActual!=null && mDistancia!=null && mDuration!=null) {
                progressBar.setVisibility(View.GONE);
                btnIr.setEnabled(true);
                tvOrigenLatitud.setText("Latitud:"+String.valueOf(mlastLocation.getLatitude()));
                tvOrigenLongitud.setText("Longitud"+String.valueOf(mlastLocation.getLongitude()));
                tvDestino.setText("Destino:" + getIntent().getStringExtra("info").replace("Info:", ""));
                tvDestinoLatitud.setText("Latitud:" + getIntent().getStringExtra("latitud").replace("Latitud:", ""));
                tvDestinoLongitud.setText("Longitud:" + getIntent().getStringExtra("longitud").replace("Longitud:", ""));
                tvOrigen.setText("Origen:" + mUbicacionActual);
                tvDistancia.setText("Distancia:"+mDistancia);
                tvTiempo.setText("Tiempo:" + mDuration);
            }
        }
    } 
在这里:

protected Document doInBackground(LatLng... params) {
                  long end;
                  end =System.currentTimeMillis();
                  Log.i("ELAPSE_PRE_BACKGROUND",((end- mStart)/1000)+"");
                  md=new GMapV2Direction();
                  end=System.currentTimeMillis();
                  Log.i("ELAPSED_POS_GMAPV2DIR",((end- mStart)/1000)+"");
                  LatLng origen=new LatLng(params[0].latitude,params[0].longitude);
                  LatLng destino=new LatLng(params[1].latitude,params[1].longitude);
                  end=System.currentTimeMillis();
                  Log.i("ELAPSED_PRE_GETDOCUMENT",((end- mStart)/1000)+"");
                  Document doc = md.getDocument(origen, destino, GMapV2Direction.MODE_WALKING);
                  end=System.currentTimeMillis();
                  Log.i("ELAPSED_POS_BACKGROUND",((end- mStart)/1000)+"");
                  /*mUbicacionActual = md.getStartAddress(doc);
                  mDuration=md.getDurationText(doc);
                  mDistancia=md.getDistanceText(doc);*/
                  return doc;

        }
在这里:

      long end=System.currentTimeMillis();
        Log.i("ELAPSED_onPostExecute",((end-mStart)/1000)+"");
        mUbicacionActual = md.getStartAddress(doc);
        mDuration=md.getDurationText(doc);
        mDistancia=md.getDistanceText(doc);
        end=System.currentTimeMillis();
        Log.i("ELAPSED_POST_FILLVARS",((end-mStart)/1000)+"");
        if (mUbicacionActual!=null && mDistancia!=null && mDuration!=null) {
            progressBar.setVisibility(View.GONE);
            btnIr.setEnabled(true);
            tvOrigenLatitud.setText("Latitud:" + String.valueOf(mlastLocation.getLatitude()));
            tvOrigenLongitud.setText("Longitud" + String.valueOf(mlastLocation.getLongitude()));
            tvDestino.setText("Destino:" + getIntent().getStringExtra("info").replace("Info:", ""));
            tvDestinoLatitud.setText("Latitud:" + getIntent().getStringExtra("latitud").replace("Latitud:", ""));
            tvDestinoLongitud.setText("Longitud:" + getIntent().getStringExtra("longitud").replace("Longitud:", ""));
            tvOrigen.setText("Origen:" + mUbicacionActual);
            tvDistancia.setText("Distancia:"+mDistancia);
            tvTiempo.setText("Tiempo:" + mDuration);
            end=System.currentTimeMillis();
            Log.i("ELAPSED_POS_onPostExecute", ((end - mStart) / 1000) + "");
        }
这张图显示了日志输出,它显示了3,但实际上是30或更多。
[IMG]

我还不能发表评论,所以你可以这样做:在两个给定代码块的每一行上放置断点后,你可以使用IDE的调试器来查看哪一行执行的时间最长。然后发布您的发现。

所花的时间与
异步任务
线程
处理程序
执行器

问题是,您正在使用的库调用服务器或处理信息确实需要那么长的时间,我认为您对此无能为力。这只是第一次,因为我猜库会缓存结果,但它仍然与您使用的线程模型无关

我回答的要点是你问错了问题。正确的问题是:

  • 为什么这个库需要这么长的时间来处理,您可以做些什么来缩短它
不幸的是,回答这个问题的唯一可能方法是分析它的源代码或直接与库开发人员交谈

编辑:

要帮助您衡量执行情况,请执行以下操作:

   public static class TimeMeasure {
      private final DecimalFormat format;
      private final double start;
      private final String tag;

      public TimeMeasure(String tag) {
         this.format = new DecimalFormat("0.0");
         this.start = System.currentTimeMillis();
         this.tag = tag;
         log("start);
      }

      public void log(String message) {
         double elapsed = ((double) (System.currentTimeMillis() - start)) / 1000.0;
         Log.d(tag, format.format(elapsed) + ": " + message);
      }
   }
然后在
doInBackground

protected Document doInBackground(LatLng... params) {
   TimeMeasure tm = new TimeMeasure("Carlos");
   // execute something:
   tm.log("action 1");
   // execute next
   tm.log("action 2);
   // etc... 
}

正如上面的回答所提到的,实际上是图书馆花费了太多的时间

不久前我遇到了一个类似的问题,我记得在调试后导致问题的原因是距离和持续时间,而且如果您得到某种地址,这将导致延迟 (例如)获取街道名称、城市名称和国家等

我没有找到更好的
API
或库来处理这个问题,但我所做的是改善用户体验:

1-从
onPostExecute()
启动另一个
AsyncTask
,该任务将获得持续时间和距离

2-当应用程序获得持续时间和距离时,不要用进度对话框或进度条阻塞用户界面,只需将加载。。。作为
TextView
的默认值,然后当应用程序收到数据时,将
setText
设置为实际值

3-在设置重要数据后,稍后进行所有数据操作


希望这会有所帮助。

异步任务实际启动前需要30秒,还是持续
doInBackground()
30秒?事实上,我怀疑第一种情况正在发生……哪一行花了最多的时间?如果你告诉我怎么做,我不知道如何跟踪应用程序。我只知道UI需要大量更新。您可以使用
Log
类,并在IDE的LogCat中查看打印的日志:@Carlos Hernández use System.currentTimeMillis();跟踪doInbackground中的时间需要花费时间。此外,我们不应该在asynctask中执行长时间运行的任务这不是asynctask的目的,如果doInbackground中的超时时间太长,请使用IntentService。我用日志更新了我的问题。我在GitHub上有代码,以防有人想测试它。类为GMapV2Direction的行似乎执行得很快。或者你指的是什么库?我猜要么是构造函数(
newgmapv2direction()
)要么是方法
getDocument(…)
。但我从命令中看到,您也遇到了问题,无法正确地度量这些执行。也许首先要解决这些问题,然后你可以确定是什么花了那么长时间。是的,我在衡量执行情况时遇到了问题,结果似乎不一致。我添加了一些代码来帮助你衡量执行情况。除非你准确地知道哪个电话花了那么长的时间,否则你将无法适当地缩小问题的范围。谢谢你的课,这里有我的结果:谢谢你的回答。持续时间和距离与onPostExecuted中的地址一起使用getDurationText和getDistanceText方法计算得非常快,因此,如果我对您有很好的了解,我认为不需要在那里执行另一个异步任务。正如你所说,问题在于图书馆。我将尝试使用json和另一个http客户端编写它。
protected Document doInBackground(LatLng... params) {
   TimeMeasure tm = new TimeMeasure("Carlos");
   // execute something:
   tm.log("action 1");
   // execute next
   tm.log("action 2);
   // etc... 
}