AsyncTask 不断重复 onResume

Posted

技术标签:

【中文标题】AsyncTask 不断重复 onResume【英文标题】:AsyncTask keeps repeating onResume 【发布时间】:2017-09-19 01:02:08 【问题描述】:

我正在制作一个从 Google Places 获取数据并在列表视图中显示数据的 android 应用程序。问题是 asynctask 不断刷新并发出 http 请求,最终导致我的适配器上的 outOfBounds 。我正在使用一项服务来获取设备的位置并将其发送到通过广播接收器获取位置的活动。

是 onResume 一直被调用的问题吗?

广播接收器的onRecieve方法是不是一直被调用?

Service 上的 locationListener 是否重复?

提前致谢!

带有 listView、broadcastReceiver 和 AsyncTask 的 Activity:

public class NearbyLocationsActivity extends BaseActivity implements AsyncDelegate 
private Location mLastLocation;
private GetLocations nearbyLocations;
private PlaceAdapter adapter;

private ArrayList<Place> nearbyPlaces;

private double mLat;
private double mLong;

private ListView locationsList;

public Spinner typesSpinner;

private BroadcastReceiver broadcastReceiver;

private String radius = "10000";

private int selectedSpinnerIndex;

private String [] types = "everything", "restaurant", "bar", "museum", "night_club", "cafe", "movie_theater";

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_nearby_locations);

    locationsList = (ListView) findViewById(R.id.locations_list);
    typesSpinner = (Spinner) findViewById(R.id.type_spinner);

    nearbyPlaces = new ArrayList();

    adapter = new PlaceAdapter(getApplicationContext(), nearbyPlaces);
    locationsList.setAdapter(adapter);

    if(!runtimePermissions()) 
        enableService();
    


@Override
public boolean onCreateOptionsMenu(Menu menu) 
    super.onCreateOptionsMenu(menu);

    return true;


public void enableService() 
    Intent i = new Intent(getApplicationContext(), LocationService.class);
    startService(i);


private boolean runtimePermissions() 
    if (Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED
            && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) 

            requestPermissions(new String[]Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION, 100);
            return true;
    
    return false;


@Override
public void onResume() 
    super.onResume();
    if (broadcastReceiver == null) 
        broadcastReceiver = new BroadcastReceiver() 
            @Override
            public void onReceive(Context context, Intent intent) 
                mLastLocation = (Location) intent.getExtras().get("coordinates");
                mLat = mLastLocation.getLatitude();
                mLong = mLastLocation.getLongitude();

                nearbyLocations = new GetLocations(NearbyLocationsActivity.this);
                nearbyLocations.execute();
            
        ;
    
    registerReceiver(broadcastReceiver, new IntentFilter("location_updates"));


@Override
public void onDestroy() 
    super.onDestroy();
    if (broadcastReceiver != null) 
        unregisterReceiver(broadcastReceiver);
    


@Override
public void onStop() 
    Intent i = new Intent(getApplicationContext(), LocationService.class);
    stopService(i);
    super.onStop();


@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) 
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 100) 
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) 
            enableService();
         else 
            runtimePermissions();
        
    


@Override
public void asyncComplete(boolean success) 
    typesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() 
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) 
            selectedSpinnerIndex = typesSpinner.getSelectedItemPosition();
            new GetLocations(NearbyLocationsActivity.this).execute();
        

        @Override
        public void onNothingSelected(AdapterView<?> parent) 
            selectedSpinnerIndex = 0;
        
    );

    locationsList.setOnItemClickListener(new AdapterView.OnItemClickListener() 
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
            Place p = adapter.getItem(position);
            Intent intent = new Intent(getApplicationContext(), CreateEventActivity.class);
            intent.putExtra("selectedPlace", p);
            startActivity(intent);
        
    );


public class GetLocations extends AsyncTask<Void, Void, Void> 

    private AsyncDelegate delegate;

    public GetLocations (AsyncDelegate delegate)
        this.delegate = delegate;
    

    @Override
    protected Void doInBackground(Void... params) 
        nearbyPlaces.clear();
        StringBuilder sb = new StringBuilder();
        String http = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=" + mLat + "," + mLong +
                "&radius=10000";

        if (selectedSpinnerIndex != 0) 
            http += "&types=" + types[selectedSpinnerIndex];
        

        http += "&key=AIzaSyDFb37i6VGPj2EG6L7dLO5H7tDhLCqCW2k";

        HttpURLConnection urlConnection;
        try 
            URL url = new URL(http);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");

            if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) 
                InputStream in = new BufferedInputStream(urlConnection.getInputStream());
                BufferedReader reader = new BufferedReader(new InputStreamReader(in));

                String line;
                while ((line = reader.readLine()) != null) 
                    sb.append(line);
                
            

            JSONObject jsonObject = new JSONObject(sb.toString());
            JSONArray array = jsonObject.getJSONArray("results");

            for (int i = 0; i < array.length(); i++) 
                JSONObject placeLine = (JSONObject) array.get(i);
                Place place = new Place();
                JSONObject geometryLine = placeLine.getJSONObject("geometry");
                JSONObject locationLine = geometryLine.getJSONObject("location");
                Place.Location location = new Place.Location();
                location.setLat(locationLine.getDouble("lat"));
                location.setLon(locationLine.getDouble("lng"));
                place.setLocation(location);
                place.setIcon(placeLine.getString("icon"));
                place.setPlaceId(placeLine.getString("place_id"));

                String detailsHttp = "https://maps.googleapis.com/maps/api/place/details/json?key=AIzaSyDFb37i6VGPj2EG6L7dLO5H7tDhLCqCW2k&placeid=" + place.getPlaceId();
                getPlaceDetails(detailsHttp, place);

                place.setName(placeLine.getString("name"));

                /*JSONArray typesJson = new JSONArray("types");
                String [] types = new String[typesJson.length()];
                for (int a = 0; i < typesJson.length(); i++) 
                    types[a] = typesJson.getString(a);
                
                place.setTypes(types);*/

                place.setVicinity(placeLine.getString("vicinity"));

                try 
                    place.setRating(placeLine.getInt("rating"));
                 catch (JSONException je) 
                    place.setRating(-1);
                

                try 
                    JSONArray photosJson = placeLine.getJSONArray("photos");
                    //for (int k = 0; i < photosJson.length(); i++) 
                        JSONObject photoLine = (JSONObject) photosJson.get(0);

                        String photoHttp = "https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&" +
                                "photoreference=" + photoLine.getString("photo_reference") + "&key=AIzaSyDFb37i6VGPj2EG6L7dLO5H7tDhLCqCW2k";

                        place.setPhotoHttp(photoHttp);
                        //place.addPhotoHttp(photoHttp);
                    //
                 catch (JSONException je) 
                    place.setPhotoHttp(null);
                
                nearbyPlaces.add(place);
            

         catch(MalformedURLException mue)
            System.out.println("A malformed URL exception occurred. " + mue.getMessage());
         catch(IOException ioe)
            System.out.println("A input/output exception occurred. " + ioe.getMessage());
         catch(JSONException je)
            System.out.println("A JSON error occurred. " + je.getMessage());
        

        return null;
    

    public void getPlaceDetails(String http, Place p) 
        StringBuilder sb = new StringBuilder();
        HttpURLConnection urlConnection;
        try 
            URL url = new URL(http);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");

            if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) 
                InputStream in = new BufferedInputStream(urlConnection.getInputStream());
                BufferedReader reader = new BufferedReader(new InputStreamReader(in));

                String line;
                while ((line = reader.readLine()) != null) 
                    sb.append(line);
                
            

            JSONObject jsonObject = new JSONObject(sb.toString());
            JSONObject resultsJson = jsonObject.getJSONObject("result");
            String address = resultsJson.getString("formatted_address");
            p.setAddress(address);
         catch(MalformedURLException mue)
            System.out.println("A malformed URL exception occurred. " + mue.getMessage());
         catch(IOException ioe)
            System.out.println("A input/output exception occurred. " + ioe.getMessage());
         catch(JSONException je)
            System.out.println("A JSON error occurred. " + je.getMessage());
        
    

    @Override
    protected void onPostExecute(Void aVoid) 
        // Thread is finished downloading and parsing JSON, asyncComplete is
        adapter.notifyDataSetChanged();
        delegate.asyncComplete(true);
    

检索设备位置的服务:

public class LocationService extends Service 

private LocationListener listener;
private LocationManager locationManager;

@Override
public void onCreate() 
    super.onCreate();

    listener = new LocationListener() 
        @Override
        public void onLocationChanged(Location location) 
            Intent i = new Intent("location_updates");
            i.putExtra("coordinates", location);
            sendBroadcast(i);
        

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) 

        

        @Override
        public void onProviderEnabled(String provider) 

        

        @Override
        public void onProviderDisabled(String provider) 
            Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(i);
        
    ;

    locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);

    //noinspection MissingPermission
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 0, listener);


@Override
public void onDestroy() 
    super.onDestroy();
    if (locationManager != null) 
        locationManager.removeUpdates(listener);
    


public IBinder onBind(Intent intent) 
    return null;

列表视图的适配器:

public class PlaceAdapter extends ArrayAdapter<Place> 
private Context mContext;
private ArrayList<Place> places;

public PlaceAdapter(Context context, ArrayList<Place> nearbyPlaces) 
    super(context, R.layout.place_list_item, nearbyPlaces);
    mContext = context;
    this.places = nearbyPlaces;


@Override
public View getView(final int position, View convertView, ViewGroup parent) 
    LayoutInflater inflater = LayoutInflater.from(mContext);
    View view = inflater.inflate(R.layout.place_list_item, null);

    final Place p = places.get(position);

    TextView placeName = (TextView) view.findViewById(R.id.place_name);
    placeName.setText(p.getName());

    TextView placeAddress = (TextView) view.findViewById(R.id.place_address);
    placeAddress.setText(p.getAddress());

    ImageView placeImage = (ImageView) view.findViewById(R.id.place_picture);

    if (p.getPhotoHttp() != null) 
        Picasso.with(mContext).load(p.getPhotoHttp()).into(placeImage);
     else 
        Picasso.with(mContext).load(p.getIcon()).into(placeImage);
    

    return view;

【问题讨论】:

【参考方案1】:
@Override
public void onResume() 
    super.onResume();
    if (broadcastReceiver == null) 
        broadcastReceiver = new BroadcastReceiver() 
            @Override
            public void onReceive(Context context, Intent intent) 
                mLastLocation = (Location) intent.getExtras().get("coordinates");
                mLat = mLastLocation.getLatitude();
                mLong = mLastLocation.getLongitude();

                nearbyLocations = new GetLocations(NearbyLocationsActivity.this);
                nearbyLocations.execute();
            
        ;
        registerReceiver(broadcastReceiver, new IntentFilter("location_updates"));
    

将 registerReceiver 移入 if 块

【讨论】:

以上是关于AsyncTask 不断重复 onResume的主要内容,如果未能解决你的问题,请参考以下文章

AsyncTask 不断崩溃在 Android 模拟器上运行的演示应用程序

如何在Android中强制停止AsyncTask [重复]

AsyncTask 和进度条 [重复]

调用 AsyncTask.get() 时未显示 ProgressDialog [重复]

从Android中的AsyncTask返回一个值[重复]

AsyncTask上的IllegalStateException [重复]