简体   繁体   English

在asynctask中每x次更新标记位置

[英]update marker position every x time in asynctask

I wanted to mock location of a marker on map. 我想模拟标记在地图上的位置。 I have list of LatLng values store in ArrayList. 我在ArrayList中存储了LatLng值的列表。 I use this value to update on map every second. 我使用此值每秒更新一次地图。 I need this function to works in AsyncTask so that my UI thread will still responsive. 我需要此函数在AsyncTask中工作,以便我的UI线程仍然可以响应。

Initially, I tried using Thread.sleep() but made application not responsive. 最初,我尝试使用Thread.sleep()但使应用程序无响应。

protected String doInBackground(Void... voids) {
    new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < waypoint.size(); i++) {
                marker = googleMap.addMarker(new MarkerOptions().position(waypoint.get(0)));
                marker.setPosition(waypoint.get(i));
                try {
                    Thread.sleep(1000); // Thread sleep made application not responsive.
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }, 500);
    return null;
}

I also tried using .postDelayed but the integer i needs to get declared final which is a problem because I need the integer to change value. 我也尝试使用.postDelayed但是i需要将整数声明为final,这是一个问题,因为我需要使用整数来更改值。

protected String doInBackground(Void... voids) {
    for (int i = 0; i < waypoint.size(); i++) {
        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
            @Override
            public void run() {
                marker = googleMap.addMarker(new MarkerOptions().position(waypoint.get(0)));
                marker.setPosition(waypoint.get(i)); // Integer i needs to declare final.
            }
        }, 1000);
    }
    return null;
}

Is there any way to do this? 有什么办法吗? Thank you. 谢谢。

The Thread.sleep() approach is OK if you can spare a worker thread. 如果您可以保留工作线程,则Thread.sleep()方法是可以的。 The problem in your code is that the thread you are pausing is the UI Thread, that's why your application freezes. 代码中的问题是您正在暂停的线程是UI线程,这就是您的应用程序冻结的原因。 You have to understand that what your doing there is just publishing a runnable to the UI Thread using the Handler construct, nothing more. 您必须了解,您所做的只是使用Handler构造将可运行对象发布到UI线程,仅此而已。

In your second approach, you can dump the Handler part and use publishProgress (called from the background) after you override onProgressUpdate (delivered in UI thread) in your AsyncTask based class. 在第二种方法中,可以在基于AsyncTask的类中重写onProgressUpdate (在UI线程中提供)后,转储Handler部分并使用publishProgress (从后台调用)。 It does effectively the same but with less boilerplate. 它的作用相同,但样板更少。 Take a look at https://developer.android.com/reference/android/os/AsyncTask for details. 查看https://developer.android.com/reference/android/os/AsyncTask了解详细信息。

Finally, to circumvent the final requirement in anonymous classes, you can declare a final array of one element and use position 0 to read/write the value. 最后,为了规避匿名类的最终要求,您可以声明一个元素的最终数组,并使用位置0读取/写入该值。 Hopefully, you won't need to do this too often. 希望您不需要经常这样做。

The fastest (but not the most correct when working with MultiThreading) way is: 最快的方法(但在使用多线程时不是最正确的方法)是:

protected String doInBackground(Void... voids) {
for (final TYPE_OF_WAYPOINT cWaypoint : waypoint) {
    new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
        @Override
        public void run() {
            marker = googleMap.addMarker(new MarkerOptions().position(waypoint.get(0)));
            marker.setPosition(cWaypoint);
        }
    }, 1000);
}
return null;

} }

I don't know what was the Type of "waypoint" List, so I wrote "TYPE_OF_WAYPOINTS" as placeholder. 我不知道“路标”列表的类型是什么,所以我写了“ TYPE_OF_WAYPOINTS”作为占位符。

@emandt answer does not work but the idea he gave could work. @emandt的答案不起作用,但是他给出的想法可以起作用。 So I tried and it is working flawlessly with some modified from his answer: 所以我尝试了一下,并且从他的答案中进行了一些修改后,它可以完美地工作:

protected String doInBackground(Void... voids) {
for (final TYPE_OF_WAYPOINT cWaypoint : waypoint) {
    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            marker = googleMap.addMarker(new MarkerOptions().position(waypoint.get(0)));
            marker.setPosition(cWaypoint);
        }
    });
    try {
        Thread.sleep(1000);
    } catch (Exception e) {
        // catch exception here
    }
}
return null;
}

Firstly, I have change the .postDelayed to .post . 首先,我将.postDelayed更改为.post Then, to delay the operation by one second, I have added Thread.sleep(1000) inside for (...) but outside new Handler(Looper.getMainLooper()).post(...)); 然后,为了将操作延迟一秒,我在for (...)内部添加了Thread.sleep(1000) for (...)但在new Handler(Looper.getMainLooper()).post(...));外部添加了Thread.sleep(1000) new Handler(Looper.getMainLooper()).post(...)); .

Now, the application could do the process in the background with user still be able to interact with the UI. 现在,应用程序可以在后台执行该过程,而用户仍然可以与UI进行交互。 Thanks. 谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM