如何使用 onCreate() 更新天气?

How to update weather with onCreate()?

我一直在开发天气应用程序,我知道它并不完美(我才刚刚开始 android 开发),但我不确定如何更新天气信息每次启动。我试图将所有内容都保留在 onCreate() 方法中,但它只是 "sticks" 我刚开始时使用的位置和条件。

我已经能够通过按下按钮获取新位置和天气状况的按钮来解决这个问题,但这不是很直观。我想知道如何在应用程序启动时获得新条件。可能涉及调用 onRestart()?

这是我在应用程序中唯一的 activity:

package com.photonfighterlabs.dropweather;

import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.ftoslab.openweatherretrieverz.CurrentWeatherInfo;
import com.ftoslab.openweatherretrieverz.OpenWeatherRetrieverZ;
import com.ftoslab.openweatherretrieverz.WeatherCallback;
import com.ftoslab.openweatherretrieverz.WeatherUnitConverter;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.tasks.OnSuccessListener;

import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class WeatherActivity extends Activity {

    private double lat;
    private double lng;

    private String temp;
    private String icon;

    private TextView tempTextView;
    private TextView cityTextView;
    private TextView conditionsTextView;

    private int LOCATION_PERMISSION_ID = 1001;

    CurrentWeatherInfo currentWeatherInfoF;

    private String city;
    private List<Address> addresses;

    private FusedLocationProviderClient mFusedLocationClient;

    OpenWeatherRetrieverZ retriever;

    ImageView image;

    Geocoder geocoder;

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_weather);

        retriever = new OpenWeatherRetrieverZ(API_KEY); // hidden for obvious reasons, but working


        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        geocoder = new Geocoder(this, Locale.getDefault());

        tempTextView = (TextView) findViewById(R.id.temp_text_view);
        cityTextView = (TextView) findViewById(R.id.city_text_view);
        conditionsTextView = (TextView) findViewById(R.id.conditions_text_view);

        image = (ImageView) findViewById(R.id.conditions_image);






        if (ContextCompat.checkSelfPermission(WeatherActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(WeatherActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_ID);
            return;
        }

        mFusedLocationClient.getLastLocation()
                .addOnSuccessListener(this, new OnSuccessListener<Location>() {
                    @Override
                    public void onSuccess(Location location) {
                        if (location != null)
                            lat = location.getLatitude();
                        lng = location.getLongitude();

                        try {
                            addresses = geocoder.getFromLocation(lat, lng, 1);

                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        if (!addresses.isEmpty()) {
                            city = addresses.get(0).getLocality();
                            cityTextView.setText("Current Weather - " + city);
                            Log.d("City", city);
                        }

                        Log.d("LAT", String.valueOf(lat));
                        Log.d("LNG", String.valueOf(lng));
                    }
                });

        retriever.updateCurrentWeatherInfo(lat, lng, new WeatherCallback() {
            @Override
            public void onReceiveWeatherInfo(CurrentWeatherInfo currentWeatherInfo) {
                currentWeatherInfoF = WeatherUnitConverter.convertToImperial(currentWeatherInfo);

            }

            @Override
            public void onFailure(String error) {
                Toast.makeText(WeatherActivity.this, error, Toast.LENGTH_SHORT).show();
            }
        });

    }

    public void onRetrieveButtonClick(View view) {

        mFusedLocationClient.getLastLocation()
                .addOnSuccessListener(this, new OnSuccessListener<Location>() {
                    @Override
                    public void onSuccess(Location location) {
                        if (location != null)
                            lat = location.getLatitude();
                        lng = location.getLongitude();

                        try {
                            addresses = geocoder.getFromLocation(lat, lng, 1);

                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        if (!addresses.isEmpty()) {
                            city = addresses.get(0).getLocality();
                            cityTextView.setText("Current Weather - " + city);
                            Log.d("City", city);
                        }

                        Log.d("LAT", String.valueOf(lat));
                        Log.d("LNG", String.valueOf(lng));
                    }
                });


        retriever.updateCurrentWeatherInfo(lat, lng, new WeatherCallback() {
            @Override
            public void onReceiveWeatherInfo(CurrentWeatherInfo currentWeatherInfo) {
                currentWeatherInfoF = WeatherUnitConverter.convertToImperial(currentWeatherInfo);

            }

            @Override
            public void onFailure(String error) {
                Toast.makeText(WeatherActivity.this, error, Toast.LENGTH_SHORT).show();
            }
        });

        temp = currentWeatherInfoF.getCurrentTemperature();

        Log.d("TMP : ", String.valueOf(temp));

        tempTextView.setText( String.valueOf((int) Double.parseDouble(temp)) + (char) 0x00B0);
        conditionsTextView.setText(currentWeatherInfoF.getWeatherDescriptionLong());


        String iconURL = currentWeatherInfoF.getWeatherIconLink().toString();

        Pattern p = Pattern.compile("\d\w(n|d)");
        Matcher m = p.matcher(iconURL);


        if (m.find()) {
            icon = m.group();
            Log.d("ICON", icon);
            String iconName = "r" + icon;
            image.setImageResource(getResources().getIdentifier(iconName, "drawable", getPackageName()));
            Log.d("NAME", iconName);
        }

    }




}

getLastLocation()updateCurrentWeatherInfo(...)都是异步操作。您同时启动它们,这意味着 updateCurrentWeatherInfo 很可能会 运行 在职位可用之前。

必须在获得位置后才能启动它,例如从 onSuccess 侦听器。

您试过 onResume() 方法吗?

您可以使用它,当视图可见时 wi

Awareness offers a snapshot-API for obtaining the weather via getWeather() API 设备位置的方法,无需管理位置访问或与按需从服务器查询天气的 API 集成。

说明性代码片段:

Awareness.SnapshotApi.getWeather(mGoogleApiClient)
  .setResultCallback(new ResultCallback<WeatherResult>() {
    @Override
    public void onResult(@NonNull WeatherResult weatherResult) {
      if (!weatherResult.getStatus().isSuccess()) {
        Log.e(TAG, "Could not get weather.");
        return;
       }
       Weather weather = weatherResult.getWeather();
       Log.i(TAG, "Weather: " + weather);
    }
  });

请参考here了解天气class的描述,其实例由API返回。

使用它的好处是你可以大大简化你的代码,避免必须管理位置请求并根据需要经常调用 API(我相信它有一个缓存来避免太多的网络请求正在耗尽电池电量)。