这是我的应用程序的基本生命周期。它现在针对的是 SDK 版本 8,因为我仍在我的设备上运行 Android 2.3.3。
- 应用程序启动,
onResume()
被调用
方法show()
被调用来显示缓存的数据。 - 后台服务开始下载和存储数据。它使用
AsyncTask
实例来完成它的工作。 - 其中一项任务将下载的数据存储在 SQLite 数据库中。
onPostExecute()
存储任务完成后会发送广播意图。MapActivity
接收意图并处理它。
调用该方法show()
以显示缓存和新数据。
在该方法show()
中,地图视图在添加叠加层后失效。show()
当从 MapActivity 本身调用时,这可以正常工作。但是,当异步任务是方法调用的来源(间接)时,它会引发异常。
据我了解,当我在这两种情况下触发时,我都在UI 线程show()
。这是真的?
public class CustomMapActivity extends MapChangeActivity {
private boolean showIsActive = false;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(IntentActions.FINISHED_STORING)) {
onFinishedStoring(intent);
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerReceiver(mReceiver, new IntentFilter(IntentActions.FINISHED_STORING));
}
@Override
protected void onResume() {
super.onResume();
show();
}
@Override
protected void onMapZoomPan() {
loadData();
show();
}
@Override
protected void onMapPan() {
loadData();
show();
}
@Override
protected void onMapZoom() {
loadData();
show();
}
private void onFinishedStoring(Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
boolean success = extras.getBoolean(BundleKeys.STORING_STATE);
if (success) {
show();
}
}
private void loadData() {
// Downloads data in a AsyncTask
// Stores data in AsyncTask
}
private void show() {
if (showIsActive) {
return;
}
showIsActive = true;
Uri uri = UriHelper.getUri();
if (uri == null) {
showIsActive = false;
return;
}
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
List<Overlay> mapOverlays = mapView.getOverlays();
CustomItemizedOverlay overlay = ItemizedOverlayFactory.getCustomizedOverlay(this, cursor);
if (overlay != null) {
mapOverlays.clear();
mapOverlays.add(overlay);
}
}
cursor.close();
mapView.invalidate(); // throws CalledFromWrongThreadException
showIsActive = false;
}
}
这是堆栈跟踪...
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRoot.checkThread(ViewRoot.java:3020)
at android.view.ViewRoot.invalidateChild(ViewRoot.java:647)
at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:673)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:2511)
at android.view.View.invalidate(View.java:5332)
at info.metadude.trees.activities.CustomMapActivity.showTrees(CustomMapActivity.java:278)
at info.metadude.trees.activities.CustomMapActivity.onMapPan(CustomMapActivity.java:126)
at info.metadude.trees.activities.MapChangeActivity$MapViewChangeListener.onChange(MapChangeActivity.java:50)
at com.bricolsoftconsulting.mapchange.MyMapView$1.run(MyMapView.java:131)
at java.util.Timer$TimerImpl.run(Timer.java:284)
注意:我使用MapChange项目来接收有关地图事件的通知。
编辑:
从我现在在有关 AsyncTask 的文档中读到的内容(向下滚动一点),我不确定我是否以正确的方式使用它。如前所述,我从一个类中启动AsyncTask
实例。Service
相反,文档指出......
AsyncTask 允许您在用户界面上执行异步工作。它在工作线程中执行阻塞操作,然后在 UI 线程上发布结果,而无需您自己处理线程和/或处理程序。
...听起来好像AsyncTask
只能在 a 内使用,Activity
而不是在 a 内使用Service
?!