这一直让我对线程感到困惑。
我有一个使用LocationManager查找Android设备当前位置的线程。然后我更新UI以显示该位置。
事实上,我已经构建了一个名为LocationFinder的整个类来获取我的位置。这样我可以说
String yourLocation = (new LocationFinder).getLocation();
但是,LocationFinder中的getLocation()方法在单独的线程上运行。所以我实际上不能说
String yourLocation = (new LocationFinder).getLocation();
因为返回的立即值肯定不是位置,因为该位置需要几分之一秒才能找到。 getLocation()默认返回“notset”,直到内部方法将返回值设置为实际位置。
无论如何,我对如何处理这个问题感到困惑。在找到该位置之前我不想阻止,因为应用程序锁定这几毫秒是非常烦人的。我不想使用AsyncTask,因为当我调用getLocation()时,已经已经,我觉得嵌套的AsyncTasks是错误的。
以下是此层次结构的伪代码:
public class MainActivity extends Activity {
Button locationButton = new Button(locationButtonClickListener);
LocationFinder locationFinder = new LocationFinder();
OnClickListener locationButtonClickListener = new OnClickListener() {
locationButton.setText(locationFinder.getLocation());
}
}
public class LocationFinder {
String city = "notYetSet";
public String getLastLocation() {
(new LastKnownLocationFinder).execute();
return city;
}
public String getGPSLocation() {
(new GPSLocationFinder).execute();
return city;
}
private class LastKnownLocationFinder extends AsyncTask {
protected String doInBackground {
city = [lots of code to get last known location];
}
}
private class GPSLocationFinder extends AsyncTask {
protected String doInBackground {
city = [lots of code to get location using GPS];
}
}
}
希望这说明了我的目标。
谢谢。
答案 0 :(得分:1)
您可以使用LocationListener。通过这种方式,只要新位置可用,您的代码就会立即运行,并且您不必阻止线程。
了解详情:http://developer.android.com/reference/android/location/LocationListener.html
答案 1 :(得分:1)
我会将应用程序使用的最后一个城市位置存储在首选项中。
每次应用程序启动/重新启动时,我都会在自己的后台线程中获取LastLocation()(或者更准确地说,每次应用程序恢复其ui线程时),我会将生成的城市存储在我上面提到的首选项中。由于该方法不会启动天线并且不会耗尽电池,因此我不会经常这样做。
回答你标题中的原始问题,不,“等待线程不会破坏使用线程的目的”。在这种情况下,“等待”一词可能令人困惑。在此期间“等待”显示并呈现完美工作UI的结果与UI线程“等待”结果之前不同,它可以绘制单个像素并从UI冻结所有内容,直到结果为止因此,从这个意义上说,如果你使用两个不同的异步后台线程,只要它们从初始UI线程(而不是嵌套)分离出来并不重要。
然后,我在onclicklistener中放置的唯一代码是异步任务,它显示进度旋转轮,并在后台执行getgpslocation以将值插入首选项,并触发内容刷新。
答案 2 :(得分:1)
线程可以将工作分开,并且大部分时间都是并行运行(异步),它们几乎没有其他原因。在某些情况下,需要一个线程来完成第二个线程处理结果的事情(同步)。
现在,如果您意识到两个线程的工作在100%的时间是顺序的,那么理论上,不需要有两个线程。除非有时人们想要将不同的工作封装在不同的组件中。
对于Android,应用程序以一个线程(UI线程/主线程)开始,该线程用于控制所有UI元素更改,并且永远不应被阻止或进入休眠状态或长时间操作生效它,这是为了减少用户遇到的任何滞后或反应迟钝(这是你目前正在做的事情)。
在你的情况下,一切似乎都是正确的,除了一件事,从我在你的伪代码中可以理解的,getLocation()
在调用时总会返回“notset”,因为没有足够的时间AsyncTask可以完全执行和更改值。
您应该构建一个interface
来在LocationFinder
和MainActivity
之间进行通信,以便在找到位置信号后发送,甚至可能只是立即发送该位置。
public class LocationFinder {
private CommunicateLocationFinder mCommunicate;
public interface CommunicateLocationFinder {
void LocationFinderSendGpsLocation(String location);
}
public LocationFinder (Activity activity){
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCommunicate = (CommunicateLocationFinder) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement CommunicateLocationFinder");
}
}
private class GpsLocationFinder extends AsyncTask {
protected String doInBackground {
/*
* Your work here
*/
}
protected void onPostExecute (String result){
mCommunicate.LocationFinderSendGpsLocation(result);
}
}
/*
* Rest of your code
*/
}
public class MainActivity extends Activity implements
LocationFinder.CommunicateLocationFinder {
@Override
public void LocationFinderSendGpsLocation(String location){
locationButton.setText(location);
}
/*
* Rest of your code
*/
}
我希望有帮助,让我知道,欢呼。