f60b618227fcad8c8bd3718f4a0a64f2b7060a8b
[JavaForFun] /
1 package com.weather.information.fragment.map;
2
3 import java.io.IOException;
4 import java.util.List;
5 import java.util.Locale;
6
7 import android.app.Activity;
8 import android.content.Context;
9 import android.location.Address;
10 import android.location.Geocoder;
11 import android.os.AsyncTask;
12 import android.os.Bundle;
13 import android.support.v4.app.Fragment;
14 import android.util.Log;
15 import android.view.LayoutInflater;
16 import android.view.View;
17 import android.view.ViewGroup;
18
19 import com.weather.information.R;
20 import com.weather.information.model.WeatherLocation;
21
22 /**
23  * {@link http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html}
24  *
25  */
26 public class MapProgressFragment extends Fragment {
27
28         /**
29          * 
30          * Callback interface through which the fragment will report the
31          * task's progress and results back to the Activity.
32          */
33         public static interface TaskCallbacks {
34                 void onPostExecute(final WeatherLocation weatherLocation);
35         }
36         
37         private TaskCallbacks mCallbacks;
38         
39     @Override
40     public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
41                              final Bundle savedInstanceState) {
42     
43         // Inflate the layout for this fragment
44         return inflater.inflate(R.layout.weather_map_progress, container, false);
45     }
46     
47     /**
48      * This method will only be called once when the retained
49      * Fragment is first created.
50      */
51     @Override
52     public void onCreate(Bundle savedInstanceState) {
53         super.onCreate(savedInstanceState);
54         
55         // Retain this fragment across configuration changes.
56         this.setRetainInstance(true);
57         
58         final Bundle bundle = this.getArguments();
59         double latitude = bundle.getDouble("latitude");
60         double longitude = bundle.getDouble("longitude");
61         
62         // Create and execute the background task.
63         new GetAddressTask(this.getActivity().getApplicationContext()).execute(latitude, longitude);
64     }
65     
66         /**
67          * Hold a reference to the parent Activity so we can report the
68          * task's current progress and results. The Android framework 
69          * will pass us a reference to the newly created Activity after 
70          * each configuration change.
71          */
72         @Override
73         public void onAttach(final Activity activity) {
74                 super.onAttach(activity);
75                 mCallbacks = (TaskCallbacks) activity;
76         }
77         
78         /**
79          * Set the callback to null so we don't accidentally leak the 
80          * Activity instance.
81          */
82 //      @Override
83 //      public void onDetach() {
84 //              super.onDetach();
85 //              mCallbacks = null;
86 //      }
87         
88         /**
89          * I am not using onDetach because there are problems when my activity goes to background.
90          * 
91          * {@link http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html}
92          */
93         @Override
94         public void onPause() {
95                 super.onPause();
96                 mCallbacks = null;
97         }
98     
99     private class GetAddressTask extends AsyncTask<Object, Void, WeatherLocation> {
100         private static final String TAG = "GetAddressTask";
101         // Store the context passed to the AsyncTask when the system instantiates it.
102         private final Context localContext;
103
104         private GetAddressTask(final Context context) {
105                 this.localContext = context;    
106         }
107         
108         @Override
109         protected WeatherLocation doInBackground(final Object... params) {
110             final double latitude = (Double) params[0];
111             final double longitude = (Double) params[1];
112
113             WeatherLocation weatherLocation = this.doDefaultLocation(latitude, longitude);
114             try {
115                 weatherLocation = this.getLocation(latitude, longitude);
116             } catch (final Throwable e) { // Hopefully nothing goes wrong because of catching Throwable.
117                 Log.e(TAG, "GetAddressTask doInBackground exception: ", e);
118             }
119
120             return weatherLocation;
121         }
122
123         @Override
124         protected void onPostExecute(final WeatherLocation weatherLocation) {
125  
126             // Call updateUI on the UI thread.
127                 if (mCallbacks != null) {
128                         mCallbacks.onPostExecute(weatherLocation);
129                 }
130         }
131         
132         private WeatherLocation getLocation(final double latitude, final double longitude) throws IOException {
133                 // TODO: i18n Locale.getDefault()
134             final Geocoder geocoder = new Geocoder(this.localContext, Locale.US);
135             final List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
136
137             // Default values
138             WeatherLocation weatherLocation = this.doDefaultLocation(latitude, longitude);
139             
140             if (addresses != null && addresses.size() > 0) {
141                 if (addresses.get(0).getLocality() != null) {
142                         weatherLocation.setCity(addresses.get(0).getLocality());
143                 }
144                 if(addresses.get(0).getCountryName() != null) {
145                         weatherLocation.setCountry(addresses.get(0).getCountryName());
146                 }       
147             }
148
149             return weatherLocation;
150         }
151
152         private WeatherLocation doDefaultLocation(final double latitude, final double longitude) {
153                 // Default values
154             String city = this.localContext.getString(R.string.city_not_found);
155             String country = this.localContext.getString(R.string.country_not_found);
156
157             return new WeatherLocation()
158                         .setLatitude(latitude)
159                         .setLongitude(longitude)
160                         .setCity(city)
161                         .setCountry(country);
162         }
163     }
164 }