【问题标题】:Refresh panel reloads forever if a city hasn't been searched如果尚未搜索城市,则刷新面板将永远重新加载
【发布时间】:2021-10-15 22:15:22
【问题描述】:

我在我的天气应用程序上设置了一个滑动刷新面板,以便在我向下滑动刷新按钮时更新我从 API 接收到的天气数据。此功能在搜索城市时成功运行,但现在的问题是,如果我在向下滑动刷新面板之前尚未搜索任何城市,它会永远重新加载,直到我退出应用程序阻碍应用程序进程并且我的应用程序被设计在用户再次搜索城市之前不保存之前的天气数据。

我想在搜索城市之前完全停止刷新面板重新加载,或者只是限制在搜索城市之前重新加载所需的时间。请问我该怎么做?我已经检查了这个网站以寻找类似的问题/答案,但没有发现任何有助于/与我想要实现的目标相关的问题。

这是当前的刷新面板编程设置:

realSwipe.setOnRefreshListener(() -> {
                // perform the delay action
                new Handler().postDelayed(() -> {
                    // this code is for stop refreshing icon, After 1000 ms automatically refresh icon will stop
                    realSwipe.setRefreshing(false);
                }, 1000);
            });

这是我的 Fragment 的代码(以备不时之需):

public class FirstFragment extends Fragment {

    private WeatherDataViewModel viewModel;

    public FirstFragment() {
    // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_first, container, false);
        // For displaying weather data
        final TextView current_temp = rootView.findViewById(R.id.textView10);
        final TextView current_output = rootView.findViewById(R.id.textView11);
        final TextView rise_time = rootView.findViewById(R.id.textView25);
        final TextView set_time = rootView.findViewById(R.id.textView26);
        final TextView temp_out = rootView.findViewById(R.id.textView28);
        final TextView Press_out = rootView.findViewById(R.id.textView29);
        final TextView Humid_out = rootView.findViewById(R.id.textView30);
        final TextView Ws_out = rootView.findViewById(R.id.textView33);
        final TextView Visi_out = rootView.findViewById(R.id.textView34);
        final TextView Cloud_out = rootView.findViewById(R.id.textView35);
        final ImageView current_icon = rootView.findViewById(R.id.imageView6);
        final SwipeRefreshLayout realSwipe = rootView.findViewById(R.id.real_swipe);

        // Get our ViewModel instance
        viewModel = new ViewModelProvider(requireActivity()).get(WeatherDataViewModel.class);

        // And whenever the data changes, refresh the UI
        viewModel.getWeatherDataLiveData().observe(getViewLifecycleOwner(), data -> {

            realSwipe.setOnRefreshListener(() -> {
                // perform the delay action
                new Handler().postDelayed(() -> {
                    // this code is for stop refreshing icon, After 1000 ms automatically refresh icon will stop
                    realSwipe.setRefreshing(false);
                }, 1000);
            });

            int drawableResource = -1; // here define default icon for example R.drawable.default_weather_icon

            int soundResource = -1; // Default sound is nothing

            if (data != null) {
                current_temp.setVisibility(View.VISIBLE);
                current_temp.setText(data.getMain().getTemp() + " ℃"); // for that you can use strings resource and templates more in https://developer.android.com/guide/topics/resources/string-resource.html#formatting-strings
                current_output.setVisibility(View.VISIBLE);
                current_output.setText(data.getWeather().get(0).getDescription());
                rise_time.setVisibility(View.VISIBLE);
                rise_time.setText(data.getSys().getSunrise() + " ");
                set_time.setVisibility(View.VISIBLE);
                set_time.setText(data.getSys().getSunset() + " ");
                temp_out.setVisibility(View.VISIBLE);
                temp_out.setText(data.getMain().getTemp() + " ℃");
                Press_out.setVisibility(View.VISIBLE);
                Press_out.setText(data.getMain().getPressure() + " hpa");
                Humid_out.setVisibility(View.VISIBLE);
                Humid_out.setText(data.getMain().getHumidity() + " %");
                Ws_out.setVisibility(View.VISIBLE);
                Ws_out.setText(data.getWind().getSpeed() + " Km/h");
                Visi_out.setVisibility(View.VISIBLE);
                Visi_out.setText(data.getVisibility() + " m");
                Cloud_out.setVisibility(View.VISIBLE);
                Cloud_out.setText(data.getClouds().getAll() + " %");

                // get actual weather.

                String icon = data.getWeather().get(0).getIcon();

                switch (icon) {
                    case "01d":
                    case "01n":
                        drawableResource = R.drawable.sun;
                        soundResource = R.raw.clear_sky_sound;
                        break;

                    case "02d":
                    case "021n":
                        drawableResource = R.drawable.few_clouds;
                        soundResource = R.raw.clouds_sound;
                        break;

                    case "03d":
                    case "03n":
                        drawableResource = R.drawable.scattered_clouds;
                        soundResource = R.raw.clouds_sound;
                        break;

                    case "04d":
                    case "04n":
                        drawableResource = R.drawable.broken_clouds;
                        soundResource = R.raw.clouds_sound;
                        break;

                    case "09d":
                    case "09n":
                        drawableResource = R.drawable.shower_rain;
                        soundResource = R.raw.shower_rain_sound;
                        break;

                    case "10d":
                    case "10n":
                        drawableResource = R.drawable.small_rain;
                        soundResource = R.raw.shower_rain_sound;
                        break;

                    case "11d":
                    case "11n":
                        drawableResource = R.drawable.thunderstorm;
                        soundResource = R.raw.thunderstorm_sound;
                        break;

                    case "13d":
                    case "13n":
                        drawableResource = R.drawable.snow;
                        soundResource = R.raw.snow_sound;
                        break;

                    case "50d":
                    case "50n":
                        drawableResource = R.drawable.mist;
                        soundResource = R.raw.mist_sound;
                        break;
                }

                if (drawableResource != -1)
                    current_icon.setImageResource(drawableResource);
                    // set the first host instance for displaying the weather icons

                if (soundResource != -1 && viewModel.soundResource != soundResource) {
                    viewModel.soundResource = soundResource;
                    if (viewModel.getMediaPlayer() != null) {
                        // we set our soundplayer in retrospect to our viewmodel

                        // stop the playing
                        if (viewModel.getMediaPlayer().isPlaying()) {
                            viewModel.getMediaPlayer().stop();
                        }

                        // release mMediaPlayer resoruces
                        viewModel.getMediaPlayer().release();
                        viewModel.setMediaPlayer(null);
                    }

                    // Play the new resource
                    viewModel.prepareMediaPlayer(requireContext(), soundResource);

                }

            } else {
                Log.e("TAG", "No City found");
                current_temp.setVisibility(View.GONE);
                current_output.setVisibility(View.GONE);
                rise_time.setVisibility(View.GONE);
                set_time.setVisibility(View.GONE);
                temp_out.setVisibility(View.GONE);
                Press_out.setVisibility(View.GONE);
                Humid_out.setVisibility(View.GONE);
                Ws_out.setVisibility(View.GONE);
                Visi_out.setVisibility(View.GONE);
                Cloud_out.setVisibility(View.GONE);
                Toast.makeText(requireActivity(), "No City found", Toast.LENGTH_SHORT).show();
            }
        });

        return rootView;
    }

    public void getWeatherData(String name) {
// The ViewModel controls loading the data, so we just
// tell it what the new name is - this kicks off loading
// the data, which will automatically call through to
// our observe() call when the data load completes
        viewModel.setCityName(name);
    }
}

【问题讨论】:

    标签: java android android-livedata weather swiperefreshlayout


    【解决方案1】:

    现在的问题是,如果我在向下滑动刷新面板之前还没有搜索过任何城市,它会永远重新加载

    因此,只要搜索到的城市为空白/空字符串,就会出现问题。这意味着在这种情况下会触发观察到的MutuableLiveData 回调。

    因为我参与了你的last question;您在没有空字符串检查的情况下加载数据:

    private void loadData() {
        // Get the last name that was set
        String name = state.get("name");
    
        // Now kick off a load from the server
        ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
    
        Call<Example> call = apiInterface.getWeatherData(name);
    
        call.enqueue(new Callback<Example>() {
            @Override
            public void onResponse(@NonNull Call<Example> call, @NonNull Response<Example> response) {
                // Save the response we've gotten
                // This will automatically update our UI
                mutableWeatherData.setValue(response.body());
            }
    
            @Override
            public void onFailure(@NotNull Call<Example> call, @NotNull Throwable t) {
                t.printStackTrace();
            }
        });
    }
    

    解决这个问题:

    • 如果城市名为空,请提前返回
    • 在更新 UI 之前检查 API Retrofit 是否没有响应。
    private void loadData() {
        // Get the last name that was set
        String name = state.get("name");
        
        // Return early if the city name is empty
        if (name == null || name.isEmpty()) return;
    
        // Now kick off a load from the server
        ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
    
        Call<Example> call = apiInterface.getWeatherData(name);
    
        call.enqueue(new Callback<Example>() {
            @Override
            public void onResponse(@NonNull Call<Example> call, @NonNull Response<Example> response) {
            
                // Check if there is no response from the the Retrofit before updating the UI
                if (response.body() == null) return;
            
                // Save the response we've gotten
                // This will automatically update our UI
                mutableWeatherData.setValue(response.body());
            }
    
            @Override
            public void onFailure(@NotNull Call<Example> call, @NotNull Throwable t) {
                t.printStackTrace();
            }
        });
    }
    

    更新

    正如 cmets 和 chats 所指出的,期望的行为不是定期更新 UI,而是让用户从顶部滑动屏幕以更新 UI。

    要解决swipeToRefresh 重新加载问题,需要将swipeToRefresh 侦听器从LiveData 观察中移除:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
                             
        // Code is omitted  ....                 
                             
         realSwipe.setOnRefreshListener(() -> {
            // perform the delay action
            new Handler().postDelayed(() -> {
                // this code is for stop refreshing icon, After 1000 ms automatically refresh icon will stop
                realSwipe.setRefreshing(false);
            }, 1000);
        });
    
        // And whenever the data changes, refresh the UI
        viewModel.getWeatherDataLiveData().observe(getViewLifecycleOwner(), data -> {
    
            int drawableResource = -1; // here define default icon for example R.drawable.default_weather_icon
    
            int soundResource = -1; // Default sound is nothing
            
            // Rest of the code ....
    

    【讨论】:

    • 在尝试您的建议时,刷新面板的行为仍然相同,即在我退出应用程序之前仍会不断重新加载。
    • @RichardWilson 有没有其他相关代码给realSwipe
    • 另一个提示使swipeRefreshLayout.setRefreshing(false); 成为onCreateView() 中的默认行为,当您点击搜索按钮时,切换它:swipeRefreshLayout.setRefreshing(true);
    • 请我不明白,添加 realSwipe.setRefreshing(true);延迟之后,但它的行为仍然相同。你怎么看这段代码:如果用户没有搜索过城市,拒绝刷新面板?
    • 抱歉,我很困惑你希望realSwipe 实现什么......你想定期运行它以从 API 更新 UI 吗?还是让用户从顶部滑动来更新 UI?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    • 1970-01-01
    • 2019-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多