1

So, in my program i have a TabActivity which contains two tabs, one tab is a ListView and another is a MapActivity that gets started via an Intent. What i want my app to do is send a query with phones location and the name of a product and reveice a list of nearest shops that have this product, then show those shops in the map tab and show the list of them in another tab. The app starts listening for location when TabActivity is started and the communication with the server (in AsyncTask) starts as soon as location is obtained.

The problem is that when TabActivity starts, it also starts the MapActivity because it is in its first tab, and the MapActivity starts to try to add overlays on the map but there is no data yet for these overlays, because the AsyncTask in TabActivity hasnt finished getting data from the server yet, which crashes the program.

I need my app to show an empty google map when TabActivity is first opened and wait for the data to be obtained from server and then add overlays to the map to mark the shops on it. Can anyone show me how can I achieve this? I guess i should remove the Overlay making part of code from onCreate in MapActivity and put it somewhere else but i dont know where.

boogieman
  • 567
  • 2
  • 5
  • 10

3 Answers3

1

In your AsyncTask, override the onPostExecute method and make your Overlay there. This function will get called once the doInBackground method finishes. You'll most likely want to feed the results from your doInBackground stuff to the onPostExecute.

Example from here:

private class DownloadImageTask extends AsyncTask {
     protected Bitmap doInBackground(String... urls) {
         return loadImageFromNetwork(urls[0]);
     }

     protected void onPostExecute(Bitmap result) {
         mImageView.setImageBitmap(result);
     }
 }
Marc Bernstein
  • 11,423
  • 5
  • 34
  • 32
  • Thanks, Marc, but my AsyncTask is in the TabActivity and the map is in another activity, so i cant make Overlays in onPostExecute. I need to somehow pass the message from onPostExecute to my MapActivity that the data has been obtained. – boogieman May 04 '11 at 08:40
  • You can send a new intent to the MapActivity that contains the info needed to make the overlay. In MapActivity, override the onNewIntent method and handle the incoming data from the new intent there. – Marc Bernstein May 05 '11 at 17:00
  • Ive thought about this too, but i dont know how to do it and i cant find any useful info on it, all tutorials about using Intents ive found only uses them with startActivity() or startActivityForResult() methods, but i dont need to start MapActivity again because it already gets started when TabActivity starts. Is there any other method to send an intent to activity thats already running? – boogieman May 05 '11 at 23:07
  • Nope, you send the intent the same way. Intents are not just used to start new Activities, they can also be used to pass info between Activities. In my app, I have the launchMode of the activity that receives the intent set to singleTop. To do this, put android:launchMode="singleTop" in your Activity node in AndroidManifest.xml. Then in that activity, override onNewIntent(Intent intent) and retrieve the data you passed in from the intent object. – Marc Bernstein May 06 '11 at 00:12
  • The app doesnt crash now, but the intent starts a new instance of MapActivity which then takes the whole screen, and i need MapActivity to be in a tab. I guess that is because MapActivity is not on top of activity stack, because it is a part of TabActivity, and singleTop activities need to be on top of the stack or else there will be a new instance of them created on intent received just like for standard activities :/ – boogieman May 06 '11 at 08:10
  • Yeah, not sure how the TabHost affects this. You could also try singleTask instead of singleTop or perhaps some of the other launch modes. – Marc Bernstein May 06 '11 at 16:11
  • Yea, i will try it but i doubt it'll do the work. Starting to run out of patience as ive been trying to find a solution for three days now. Guess i'll just have to redesign this whole part of my app to do things in a different way. Thanks for your help Marc. – boogieman May 06 '11 at 18:53
1

A potentially better approach would be to get the current tab activity with ActivityGroup#getCurrentActivity(), check and cast to the expected MapActivity, and then call a method in that activity:

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..
    }
}

The problem with the BroadcastReceiver solution is that the broadcast goes beyond your application's sandbox, attempting to notify anyone on the device that is listening for your intent, even though only one receiver actually wants anything to do with it.

Joe
  • 42,036
  • 13
  • 45
  • 61
  • Just tried your suggestion, works flawlessly and indeed is a better aproach to what im trying to achieve. Thanks. – boogieman Jun 06 '11 at 12:52
0

I have solved this problem myself. Its really simple, just need to use a broadcast receiver.

I created a BroadcastReceiver in my MapActivity:

private BroadcastReceiver myReceiver = new BroadcastReceiver() {        
    @Override
    public void onReceive(Context context, Intent intent) {
        addMarkers();
        mapView.invalidate();
    }
};

Then i registered it in MapActivities onCreate method:

registerReceiver(myReceiver, new IntentFilter("VAISTINES.RECEIVED"));

And finally i made my AsyncTask's in TabActivity onPostExecute method send a broadcast telling that the needed data has been retrieved from server:

Intent i = new Intent("VAISTINES.RECEIVED");
sendBroadcast(i);
boogieman
  • 567
  • 2
  • 5
  • 10