#android #maps #wait #mapactivity
#Android #Карты #подождите #mapactivity
Вопрос:
Итак, в моей программе у меня есть TabActivity, который содержит две вкладки, одна вкладка — это ListView, а другая — MapActivity, которая запускается с помощью намерения. Я хочу, чтобы мое приложение отправляло запрос с указанием местоположения телефонов и названия продукта и выводило список ближайших магазинов, в которых есть этот продукт, затем показывало эти магазины на вкладке «Карта» и показывало их список на другой вкладке. Приложение начинает прослушивать местоположение при запуске TabActivity, и связь с сервером (в AsyncTask) начинается, как только местоположение получено.
Проблема в том, что когда TabActivity запускается, он также запускает MapActivity, потому что он находится на его первой вкладке, и MapActivity начинает пытаться добавить наложения на карту, но данных для этих наложений пока нет, потому что AsyncTask в TabActivity еще не закончил получение данных с сервера, что приводит к сбою программы.
Мне нужно, чтобы мое приложение показывало пустую карту Google при первом открытии TabActivity и ожидало получения данных с сервера, а затем добавляло наложения на карту, чтобы отметить магазины на ней. Кто-нибудь может показать мне, как я могу этого добиться? Я думаю, мне следует удалить часть кода, создающую оверлей, из onCreate в MapActivity и поместить ее куда-нибудь еще, но я не знаю куда.
Ответ №1:
Потенциально лучшим подходом было бы получить текущую активность вкладки с помощью ActivityGroup#getCurrentActivity(), проверить и преобразовать в ожидаемую MapActivity, а затем вызвать метод в этой активности:
protected void onPostExecute(final Bitmap result) {
final Activity activity = MyTabActivity.this.getCurrentActivity();
if (activity instanceof MyMapActivity) {
((MyMapActivity) activity).onBitmapReceived(result); // or some other method, like onMarkersReceived(), etc..
}
}
Проблема с BroadcastReceiver
решением заключается в том, что трансляция выходит за пределы изолированной среды вашего приложения, пытаясь уведомить кого-либо на устройстве, которое прослушивает ваши намерения, хотя на самом деле только один получатель хочет иметь с этим что-либо общее.
Комментарии:
1. Просто попробовал ваше предложение, работает безупречно и действительно является лучшим подходом к тому, чего я пытаюсь достичь. Спасибо.
Ответ №2:
В вашей AsyncTask переопределите метод onPostExecute и создайте там свое наложение. Эта функция будет вызвана после завершения метода doInBackground. Скорее всего, вы захотите отправить результаты из вашего материала doInBackground в onPostExecute.
Пример из здесь:
private class DownloadImageTask extends AsyncTask {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
Комментарии:
1. Спасибо, Марк, но моя AsyncTask находится в TabActivity, а карта — в другом activity, поэтому я не могу создавать оверлеи в onPostExecute. Мне нужно каким-то образом передать сообщение из onPostExecute в мой MapActivity о том, что данные получены.
2. Вы можете отправить MapActivity новое намерение, содержащее информацию, необходимую для создания наложения. В MapActivity переопределите метод onNewIntent и обработайте входящие данные из нового намерения там.
3. Я тоже думал об этом, но я не знаю, как это сделать, и я не могу найти никакой полезной информации об этом, все руководства по использованию Intents, которые я нашел, используют их только с методами startActivity () или startActivityForResult (), но мне не нужно снова запускать MapActivity, потому что он уже запускается при запуске TabActivity. Есть ли какой-либо другой способ отправить intent в activity, который уже запущен?
4. Нет, вы отправляете намерение таким же образом. Намерения используются не только для запуска новых действий, они также могут использоваться для передачи информации между действиями. В моем приложении у меня есть режим запуска activity, который получает значение intent, установленное на singleTop. Для этого поместите android:launchMode=»singleTop» в свой узел Activity в AndroidManifest.xml. Затем в этом действии переопределите onNewIntent (намерение Intent) и извлеките данные, которые вы передали, из объекта intent.
5. Приложение сейчас не аварийно завершает работу, но намерение запускает новый экземпляр MapActivity, который затем занимает весь экран, и мне нужно, чтобы MapActivity был на вкладке. Я предполагаю, что это потому, что MapActivity не находится на вершине стека activity, потому что это часть TabActivity, а действия singleTop должны быть поверх стека, иначе будет создан их новый экземпляр на основе полученного намерения, как для стандартных действий :/
Ответ №3:
Я решил эту проблему сам. Это действительно просто, просто нужно использовать широковещательный приемник.
Я создал BroadcastReceiver в моем MapActivity:
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
addMarkers();
mapView.invalidate();
}
};
Затем я зарегистрировал это в методе MapActivities onCreate:
registerReceiver(myReceiver, new IntentFilter("VAISTINES.RECEIVED"));
И, наконец, я заставил мой метод AsyncTask в TabActivity onPostExecute отправлять широковещательную рассылку, сообщающую, что необходимые данные были получены с сервера:
Intent i = new Intent("VAISTINES.RECEIVED");
sendBroadcast(i);