Android SwipeRefreshLayout.setRefreshing(false)无效的解决办法

本文探讨了在代码中调用setRefreshing(false)后SwipeRefreshLayout仍不停止刷新的原因及解决方案,包括通过debug检查代码执行路径、使用post方式刷新、调整进度条位置等方法。

明明在代码中调用了setRefreshing(false)但是,SwipeRefreshLayout却没有停止刷新,那么原因可能是

  1. 程序中调用的setRefreshing(false);根本没有被执行到,应该通过debug一步一步看,在什么地方跳过了这句代码;

  2. 程序中在该停止的地方成功调用了setRefreshing(false);但是,在其他地方,又再次调用了setRefreshing(true);往往由于不小心或者没考虑到某种情况引起。建议跟踪SwipeRefreshLayout对象,很容易找到问题。

还有的时候我们在Activity启动的时候调用setRefreshing(true)却看不见刷新效果

这个问题的可以通过如下方法解决:

post方式刷新

mSwipeLayout.post(new Runnable() {
                @Override
                public void run() {
                    mSwipeLayout.setRefreshing(true);
                }
            });

这样做的原因很简单,因为在Activity加载的过程中,需要执行onLayout操作来布局各个控件的位置,而通过setRefreshing方法的源码可以知道,这个方法里面执行了一个操作:

setTargetOffsetTopAndBottom(endTarget - mCurrentTargetOffsetTop,
                            true /* requires update */);

该方法是用来调整进度条的位置的,因此,在控件没有完成onLayout之前,控件的位置数据都是不准确的,所以显示不出来。

偏移方式刷新

在调用刷新之前,调用setProgressViewOffset(boolean scale, int start, int end) 调整进度条距离屏幕顶部的距离,个人理解是相当于执行了手动下拉刷新的操作,遇到问题的时候可尝试此方法。

 // 这句话是为了,第一次进入页面的时候显示加载进度条  
  mSwipeRefreshWidget.setProgressViewOffset(false, 0, (int) TypedValue  
    .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources()  
      .getDisplayMetrics()));  
  mSwipeRefreshWidget.setRefreshing(true);
我要做一个基于Android studio的多城市切换+短时预警天气预报app,我的天气API是在https://www.seniverse.com/products这个网站中获取的,其中我的密钥(私钥)是SH8NroqLlNNwwg323,但是我运行之后没有获取到实时数据,我要怎么做,请给我完整代码及完善步骤 这个是我的接口ApiService代码 package com.example.myapplication.network; import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Query; public interface ApiService { // 心知天气API基础地址 String BASE_URL = "https://api.seniverse.com/v3/"; // 图片中的API密钥(公钥+私钥) String PUBLIC_KEY = "PVKLD84OHMbGx9iQG"; String PRIVATE_KEY = "SH8NroqLINNwg323"; /** * 获取实时天气 * @param location 城市名称/ID(如:beijing、101010100) * @param language 语言(zh-Hans=中文) * @param unit 单位(c=摄氏度) * @param key 公钥 * @return 实时天气响应 */ @GET("weather/now.json") Call<RealTimeResponse> getRealTimeWeather( @Query("location") String location, @Query("language") String language, @Query("unit") String unit, @Query("key") String key ); /** * 获取7天预报 * @param location 城市名称/ID * @param language 语言 * @param unit 单位 * @param key 公钥 * @return 7天预报响应 */ @GET("weather/daily.json") Call<DailyForecastResponse> get7DayForecast( @Query("location") String location, @Query("language") String language, @Query("unit") String unit, @Query("key") String key, @Query("start") int start, // 开始天数(0=今天) @Query("days") int days // 预报天数(7=7天) ); // 实时天气响应模型 class RealTimeResponse { private Results[] results; public Results[] getResults() { return results; } public static class Results { private Location location; private Now now; private String last_update; public Location getLocation() { return location; } public Now getNow() { return now; } public String getLast_update() { return last_update; } } public static class Location { private String id; private String name; private String country; private String path; public String getId() { return id; } public String getName() { return name; } public String getCountry() { return country; } public String getPath() { return path; } } public static class Now { private String text; private String code; private String temperature; private String humidity; private String wind_direction; private String wind_speed; private String wind_scale; public String getText() { return text; } public String getCode() { return code; } public String getTemperature() { return temperature; } public String getHumidity() { return humidity; } public String getWind_direction() { return wind_direction; } public String getWind_speed() { return wind_speed; } public String getWind_scale() { return wind_scale; } } } // 7天预报响应模型 class DailyForecastResponse { private Results[] results; public Results[] getResults() { return results; } public static class Results { private Location location; private Daily[] daily; private String last_update; public Location getLocation() { return location; } public Daily[] getDaily() { return daily; } public String getLast_update() { return last_update; } } public static class Location { private String id; private String name; public String getId() { return id; } public String getName() { return name; } } public static class Daily { private String date; private String text_day; private String code_day; private String text_night; private String code_night; private String high; private String low; private String wind_direction; private String wind_scale; public String getDate() { return date; } public String getText_day() { return text_day; } public String getCode_day() { return code_day; } public String getText_night() { return text_night; } public String getCode_night() { return code_night; } public String getHigh() { return high; } public String getLow() { return low; } public String getWind_direction() { return wind_direction; } public String getWind_scale() { return wind_scale; } } } } 这个是我的RetrofitClient类代码 package com.example.myapplication.network; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class RetrofitClient { private static RetrofitClient instance; private final ApiService apiService; private RetrofitClient() { Retrofit retrofit = new Retrofit.Builder() .baseUrl(ApiService.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); apiService = retrofit.create(ApiService.class); } public static synchronized RetrofitClient getInstance() { if (instance == null) { instance = new RetrofitClient(); } return instance; } public ApiService getApiService() { return apiService; } } 这个是我的MainActivity.java代码 package com.example.myapplication; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.example.myapplication.adapter.ForecastAdapter; import com.example.myapplication.model.Weather; import com.example.myapplication.network.ApiService; import com.example.myapplication.network.RetrofitClient; import com.example.myapplication.utils.NetworkUtils; import com.example.myapplication.utils.SPUtils; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; public class MainActivity extends AppCompatActivity { private static final String TAG = "SeniverseWeather"; private SwipeRefreshLayout swipeRefreshLayout; private TextView tvCity, tvTemperature, tvWeather, tvHumidity, tvWind, tvUpdateTime; private ImageView ivWeatherIcon; private RecyclerView rvForecast; private ForecastAdapter forecastAdapter; private List<Weather.DailyForecast> forecastList = new ArrayList<>(); private String currentLocation = "beijing"; // 心知天气支持城市名(英文/中文)或ID private String currentCityName = "北京"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SPUtils.init(this); // 加载保存的城市 String savedLocation = SPUtils.getString("current_location", "beijing"); String savedCityName = SPUtils.getString("current_city_name", "北京"); if (savedLocation != null && !savedLocation.isEmpty()) { currentLocation = savedLocation; currentCityName = savedCityName; } initView(); setupClickListeners(); loadRealTimeWeather(); load7DayForecast(); } private void initView() { swipeRefreshLayout = findViewById(R.id.swipe_refresh_layout); tvCity = findViewById(R.id.tv_city); tvTemperature = findViewById(R.id.tv_temperature); tvWeather = findViewById(R.id.tv_weather); tvHumidity = findViewById(R.id.tv_humidity); tvWind = findViewById(R.id.tv_wind); tvUpdateTime = findViewById(R.id.tv_update_time); ivWeatherIcon = findViewById(R.id.iv_weather_icon); rvForecast = findViewById(R.id.rv_forecast); swipeRefreshLayout.setColorSchemeResources(R.color.primary); swipeRefreshLayout.setOnRefreshListener(() -> { loadRealTimeWeather(); load7DayForecast(); }); forecastAdapter = new ForecastAdapter(forecastList); rvForecast.setLayoutManager(new LinearLayoutManager(this)); rvForecast.setAdapter(forecastAdapter); } private void setupClickListeners() { Button btnCityManager = findViewById(R.id.btn_city_manager); Button btnRefresh = findViewById(R.id.btn_refresh); btnCityManager.setOnClickListener(v -> { Intent intent = new Intent(MainActivity.this, CityManagerActivity.class); startActivityForResult(intent, 1); }); btnRefresh.setOnClickListener(v -> { if (NetworkUtils.isNetworkAvailable(this)) { loadRealTimeWeather(); load7DayForecast(); Toast.makeText(this, "刷新中...", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "无网络连接", Toast.LENGTH_SHORT).show(); } }); } // 加载实时天气 private void loadRealTimeWeather() { Log.d(TAG, "加载实时天气,城市: " + currentLocation); swipeRefreshLayout.setRefreshing(true); if (!NetworkUtils.isNetworkAvailable(this)) { swipeRefreshLayout.setRefreshing(false); Toast.makeText(this, "网络不可用", Toast.LENGTH_SHORT).show(); showMockData(); return; } ApiService apiService = RetrofitClient.getInstance().getApiService(); Call<ApiService.RealTimeResponse> call = apiService.getRealTimeWeather( currentLocation, "zh-Hans", "c", ApiService.PUBLIC_KEY ); call.enqueue(new Callback<ApiService.RealTimeResponse>() { @Override public void onResponse(Call<ApiService.RealTimeResponse> call, Response<ApiService.RealTimeResponse> response) { swipeRefreshLayout.setRefreshing(false); if (response.isSuccessful() && response.body() != null && response.body().getResults() != null) { ApiService.RealTimeResponse.Results result = response.body().getResults()[0]; updateRealWeatherUI(result); } else { String errorMsg = "实时天气获取失败: " + response.code(); Log.e(TAG, errorMsg); Toast.makeText(MainActivity.this, errorMsg, Toast.LENGTH_SHORT).show(); showMockData(); } } @Override public void onFailure(Call<ApiService.RealTimeResponse> call, Throwable t) { swipeRefreshLayout.setRefreshing(false); Log.e(TAG, "实时天气请求失败", t); Toast.makeText(MainActivity.this, "请求失败: " + t.getMessage(), Toast.LENGTH_SHORT).show(); showMockData(); } }); } // 加载7天预报 private void load7DayForecast() { Log.d(TAG, "加载7天预报,城市: " + currentLocation); if (!NetworkUtils.isNetworkAvailable(this)) { Toast.makeText(this, "网络不可用", Toast.LENGTH_SHORT).show(); return; } ApiService apiService = RetrofitClient.getInstance().getApiService(); Call<ApiService.DailyForecastResponse> call = apiService.get7DayForecast( currentLocation, "zh-Hans", "c", ApiService.PUBLIC_KEY, 0, // 从今天开始 7 // 7天预报 ); call.enqueue(new Callback<ApiService.DailyForecastResponse>() { @Override public void onResponse(Call<ApiService.DailyForecastResponse> call, Response<ApiService.DailyForecastResponse> response) { if (response.isSuccessful() && response.body() != null && response.body().getResults() != null) { ApiService.DailyForecastResponse.Daily[] dailyList = response.body().getResults()[0].getDaily(); updateForecastUI(dailyList); } else { Log.e(TAG, "预报获取失败: " + response.code()); Toast.makeText(MainActivity.this, "预报获取失败", Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<ApiService.DailyForecastResponse> call, Throwable t) { Log.e(TAG, "预报请求失败", t); Toast.makeText(MainActivity.this, "预报请求失败", Toast.LENGTH_SHORT).show(); } }); } private void updateRealWeatherUI(ApiService.RealTimeResponse.Results result) { runOnUiThread(() -> { try { ApiService.RealTimeResponse.Now now = result.getNow(); tvCity.setText(result.getLocation().getName()); tvTemperature.setText(now.getTemperature() + "°C"); tvWeather.setText(now.getText()); tvHumidity.setText("湿度: " + now.getHumidity() + "%"); tvWind.setText(now.getWind_direction() + " " + now.getWind_scale() + "级"); // 格式化更新时间(如:2025-12-08T15:44:00+08:00 → 15:44) String updateTime = result.getLast_update().split("T")[1].split("\\+")[0]; tvUpdateTime.setText("更新于: " + updateTime); setWeatherIcon(now.getText()); } catch (Exception e) { Log.e(TAG, "UI更新异常", e); showMockData(); } }); } private void updateForecastUI(ApiService.DailyForecastResponse.Daily[] dailyList) { runOnUiThread(() -> { forecastList.clear(); if (dailyList == null || dailyList.length == 0) { Toast.makeText(this, "无预报数据", Toast.LENGTH_SHORT).show(); return; } for (ApiService.DailyForecastResponse.Daily daily : dailyList) { Weather.DailyForecast forecast = new Weather.DailyForecast(); forecast.setDate(formatDate(daily.getDate())); forecast.setTmp_max(daily.getHigh()); forecast.setTmp_min(daily.getLow()); forecast.setCond_txt_d(daily.getText_day()); forecast.setWind_dir(daily.getWind_direction() + " " + daily.getWind_scale() + "级"); forecastList.add(forecast); } forecastAdapter.notifyDataSetChanged(); }); } private void setWeatherIcon(String weatherText) { int iconResId = R.drawable.weather_sunny; if (weatherText == null) { ivWeatherIcon.setImageResource(iconResId); return; } if (weatherText.contains("晴")) iconResId = R.drawable.weather_sunny; else if (weatherText.contains("云") || weatherText.contains("阴")) iconResId = R.drawable.weather_cloudy; else if (weatherText.contains("雨")) iconResId = R.drawable.weather_rainy; else if (weatherText.contains("雪")) iconResId = R.drawable.weather_snowy; else if (weatherText.contains("雾") || weatherText.contains("霾")) iconResId = R.drawable.weather_foggy; ivWeatherIcon.setImageResource(iconResId); } private String formatDate(String dateStr) { try { SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); SimpleDateFormat outputFormat = new SimpleDateFormat("MM/dd E", Locale.CHINA); Date date = inputFormat.parse(dateStr); return outputFormat.format(date); } catch (Exception e) { return dateStr; } } private void showMockData() { runOnUiThread(() -> { tvCity.setText(currentCityName); tvTemperature.setText("25°C"); tvWeather.setText("晴"); tvHumidity.setText("湿度: 60%"); tvWind.setText("东南风3级"); tvUpdateTime.setText("更新于: 模拟数据"); forecastList.clear(); String[] days = {"12/08 周一", "12/09 周二", "12/10 周三"}; String[] tempsMax = {"28", "26", "24"}; String[] tempsMin = {"22", "20", "18"}; String[] weathers = {"晴", "多云", "小雨"}; String[] winds = {"东南风3级", "东风2级", "北风4级"}; for (int i = 0; i < 3; i++) { Weather.DailyForecast forecast = new Weather.DailyForecast(); forecast.setDate(days[i]); forecast.setTmp_max(tempsMax[i]); forecast.setTmp_min(tempsMin[i]); forecast.setCond_txt_d(weathers[i]); forecast.setWind_dir(winds[i]); forecastList.add(forecast); } forecastAdapter.notifyDataSetChanged(); ivWeatherIcon.setImageResource(R.drawable.weather_sunny); }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1 && resultCode == RESULT_OK && data != null) { String selectedLocation = data.getStringExtra("selected_location"); String selectedCityName = data.getStringExtra("selected_city_name"); if (selectedLocation != null && !selectedLocation.equals(currentLocation)) { currentLocation = selectedLocation; currentCityName = selectedCityName; SPUtils.putString("current_location", currentLocation); SPUtils.putString("current_city_name", currentCityName); loadRealTimeWeather(); load7DayForecast(); } } } @Override protected void onResume() { super.onResume(); loadRealTimeWeather(); load7DayForecast(); } }
最新发布
12-09
package com.weishitechsub.kdcxqwb.fragment.Adapter; import android.Manifest; import android.app.AlertDialog; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.viewholder.BaseViewHolder; import com.weishitechsub.kdcxqwb.R; import com.weishitechsub.kdcxqwb.bean.ListBean; import com.weishitechsub.kdcxqwb.utils.PackageNotificationSender; import com.weishitechsub.kdcxqwb.utils.ReminderManager; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class MyCourierAdapter extends BaseQuickAdapter<ListBean, BaseViewHolder> { private static final String TAG = "MyCourierAdapter"; private List<ListBean> mTrackList; private Context context; // 存储:每个单号最后一次被提醒到的状态(用于去重通知) private final Map<String, String> remindedStates = new ConcurrentHashMap<>(); private Handler mainHandler = new Handler(Looper.getMainLooper()); int type; // 缓存当前列表数据 private List<ListBean> currentList; public MyCourierAdapter(List<ListBean> list, Context context, int type) { super(R.layout.my_courier_adapter, list); this.context = context; this.type = type; ReminderManager.getInstance(context); // 初始化单例 // 初始化:把已经开启提醒的单号的当前状态预加载进缓存 Set<String> remindedNumbers = ReminderManager.getInstance(context).getRemindedNumbers(); for (ListBean bean : list) { if (remindedNumbers.contains(bean.getNum())) { remindedStates.put(bean.getNum(), bean.getState()); } } } @Override protected void convert(@NonNull BaseViewHolder baseViewHolder, ListBean dataBean) { String number = dataBean.getNum(); baseViewHolder.setText(R.id.tv_number, number); baseViewHolder.setText(R.id.tv_address, dataBean.getContext()); if (type == 1) { baseViewHolder.getView(R.id.tv_remind).setVisibility(View.GONE); baseViewHolder.getView(R.id.iv_remind).setVisibility(View.GONE); } else { baseViewHolder.getView(R.id.tv_remind).setVisibility(View.VISIBLE); baseViewHolder.getView(R.id.iv_remind).setVisibility(View.VISIBLE); } // 设置快递公司信息和图标 if (dataBean.getType() != null) { String trackName = getTrackName(dataBean.getType()); baseViewHolder.setText(R.id.tv_type, trackName); ImageView logo = baseViewHolder.getView(R.id.iv_logo); LinearLayout line = baseViewHolder.getView(R.id.line); TextView name = baseViewHolder.getView(R.id.tv_name); setCompanyLogo(trackName, logo, line, name); } // ===== 获取状态文本 ===== String state = dataBean.getState(); String stateText = getStateText(state); baseViewHolder.setText(R.id.tv_state, stateText != null ? stateText : "未知状态"); ImageView ivRemind = baseViewHolder.getView(R.id.iv_remind); // === 情况1:状态无效 === if (state == null || TextUtils.isEmpty(stateText)) { Log.d("stateText", state); ivRemind.setEnabled(false); ivRemind.setAlpha(0.4f); refreshRemindIcon(ivRemind, false); // 强制显示关闭图标 ivRemind.setOnClickListener(v -> { Toast.makeText(context.getApplicationContext(), "该快递状态异常或数据不全,暂不支持开启提醒功能", Toast.LENGTH_SHORT).show(); }); // 如果此前已开启提醒,则自动关闭并清除通知 boolean wasEnabled = ReminderManager.getInstance(context).isReminded(number); if (wasEnabled) { ReminderManager.getInstance(context).disableReminder(number); Log.d(TAG, "自动关闭异常单号的提醒:" + number); } } // === 情况2:终止状态(签收、退回、拒签)=== else if (isTerminatedState(state)) { ivRemind.setEnabled(true); ivRemind.setAlpha(0.5f); boolean isReminded = ReminderManager.getInstance(context).isReminded(number); refreshRemindIcon(ivRemind, isReminded); ivRemind.setOnClickListener(v -> { String tip; if (state.startsWith("3")) { tip = getSignReceivedTip(state); } else if (state.startsWith("4") || "203".equals(state)) { tip = "该快递已拒签,订单结束。"; } else if (state.startsWith("6")) { tip = "该快递已被退回。"; } else { tip = "该快递已完成,无需提醒。"; } Toast.makeText(context.getApplicationContext(), tip, Toast.LENGTH_SHORT).show(); }); // 自动关闭提醒(如果是之前开启的) if (isReminded) { ReminderManager.getInstance(context).disableReminder(number); } } // === 情况3:正常可提醒状态(如在途、派件中等)=== else { ivRemind.setEnabled(true); ivRemind.setAlpha(1.0f); boolean isReminded = ReminderManager.getInstance(context).isReminded(number); refreshRemindIcon(ivRemind, isReminded); ivRemind.setOnClickListener(v -> { // 每次点击都重新获取当前状态!不能用外面缓存的 isReminded 变量 boolean nowEnabled = ReminderManager.getInstance(context).isReminded(number); if (nowEnabled) { // 已开启 → 关闭 ReminderManager.getInstance(context).disableReminder(number); Toast.makeText(context, "已关闭提醒: " + number, Toast.LENGTH_SHORT).show(); refreshRemindIcon(ivRemind, false); } else { // 未开启 → 开启 enableReminderWithPermissionCheck(dataBean); refreshRemindIcon(ivRemind, true); // 假设成功 } }); } // 更新缓存列表 currentList = getData(); // =================================================================== // 自动提醒机制(仅对已开启提醒的单号) // =================================================================== boolean isCurrentlyReminded = ReminderManager.getInstance(context).isReminded(number); if (isCurrentlyReminded && stateText != null) { String lastState = remindedStates.get(number); // 状态发生变化,并且不是第一次加载(lastState != null) if (lastState != null && !lastState.equals(state)) { // 发送状态更新通知 String companyName = getTrackName(dataBean.getType()); sendStatusNotification(number, companyName, stateText, getNotifyContent(state)); Log.d(TAG, "【自动提醒】状态变更: " + number + " | " + lastState + " → " + state); } // 更新为最新状态 remindedStates.put(number, state); } else { // 未开启提醒则清除缓存 remindedStates.remove(number); } } @Override public void onViewRecycled(@NonNull BaseViewHolder holder) { // 防止 RecyclerView 复用时保留旧的 OnClickListener ImageView ivRemind = holder.getView(R.id.iv_remind); ivRemind.setOnClickListener(null); super.onViewRecycled(holder); } // 检查权限后开启提醒,并发送通知 private void enableReminderWithPermissionCheck(ListBean dataBean) { String number = dataBean.getNum(); String state = dataBean.getState(); String type = dataBean.getType(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { showNotificationPermissionDialog(); return; } } // 启用本地提醒记录 ReminderManager.getInstance(context).enableReminder(number); Toast.makeText(context, "已开启提醒: " + number, Toast.LENGTH_SHORT).show(); // 发送一条当前状态的通知 String companyName = getTrackName(type); sendStatusNotification(number, companyName, getStateText(state), getNotifyContent(state)); } // 刷新提醒按钮图标 private void refreshRemindIcon(ImageView ivRemind, boolean isEnabled) { if (isEnabled) { ivRemind.setImageResource(R.mipmap.button_on); } else { ivRemind.setImageResource(R.mipmap.button_off); } } // ======== 精确状态文本映射 ========= private String getStateText(String state) { if (state == null || state.isEmpty()) return null; // 统一处理主状态 if (state.startsWith("3")) return "签收"; if (state.startsWith("4")) return "退签"; if (state.startsWith("6")) return "退回"; // 清关类 if (state.startsWith("8") || "10".equals(state) || "11".equals(state) || "12".equals(state) || "13".equals(state)) { return getDetailClearanceText(state); } // 其他具体状态 switch (state) { case "0": case "1002": return "在途"; case "1001": return "到达派件城市"; case "1003": return "转递中"; case "1": case "101": return "已下单"; case "102": return "待揽收"; case "103": return "已揽收"; case "5": return "派件中"; case "501": return "已投柜/驿站"; case "7": return "转投"; case "2": return "疑难"; case "201": return "超时未签收"; case "202": return "超时未更新"; case "203": return "拒收"; case "204": return "派件异常"; default: return null; } } // 清关详情 private String getDetailClearanceText(String state) { switch (state) { case "8": return "清关"; case "10": return "待清关"; case "11": return "清关中"; case "12": return "已清关"; case "13": return "清关异常"; default: return "清关"; } } // ======== 是否为终止状态(不能再提醒)======== private boolean isTerminatedState(String state) { if (state == null || state.isEmpty()) return false; char firstChar = state.charAt(0); // 主状态为 3(签收)、4(退签)、6(退回) 的都算终止 if (firstChar == '3' || firstChar == '4' || firstChar == '6') { return true; } // 特殊子状态:203 拒收 → 也视为终止 return "203".equals(state); } // ======== 签收提示语 ======== private String getSignReceivedTip(String state) { switch (state) { case "301": return "该快递已由本人签收,无需提醒。"; case "302": return "该快递在派件异常后完成签收。"; case "303": return "该快递已被他人代签,请注意查收。"; case "304": return "该快递已投入快递柜或驿站签收。"; default: return "该快递已签收,无需提醒。"; } } // ======== 通知内容(更精准)======== private String getNotifyContent(String state) { if (state == null) return "快递状态已更新,请注意查看。"; // 签收类统一处理 if (state.startsWith("3")) { return getSignReceivedTip(state); } switch (state) { // --- 在途 --- case "0": case "1002": return "您的快递已在运输途中,正在路上~"; case "1001": return "快递已到达派件城市,即将开始派送!"; case "1003": return "快递正在转递至下一个中转站点。"; // --- 揽收 --- case "1": case "101": return "已生成运单,请等待快递员上门揽收。"; case "102": return "快递员即将上门揽收,请准备好包裹。"; case "103": return "包裹已被成功揽收,进入运输流程。"; // --- 派件 --- case "5": return "快递员正在为您派送,请注意查收!"; case "501": return "快递已投入智能快递柜或驿站,请及时取件。"; // --- 转投 --- case "7": return "因地址问题,快递已转投其他网点处理。"; // --- 疑难 --- case "201": return "快递长时间未签收,请联系发件人确认。"; case "202": return "物流信息长时间未更新,请留意异常情况。"; case "203": return "您已申请拒收,快递将按流程退回。"; case "204": return "快递派送过程中出现异常,请关注后续更新。"; // --- 退回 & 退签 --- case "6": return "很遗憾,您的快递因故被退回。"; case "4": return "您已拒签该快递,订单已完成。"; default: return "快递状态已更新,请注意查看最新动态。"; } } // 发送状态变更通知 private void sendStatusNotification(String number, String company, String titleSuffix, String content) { PackageNotificationSender sender = new PackageNotificationSender(context); int id = ("status_" + number).hashCode() & Integer.MAX_VALUE; id = (id % 1_000_000) + 2000; // 避免 ID 冲突 sender.sendCustomNotification(id, "📌 快递" + titleSuffix, content, number, company); } // 根据 type 查找快递公司名称 private String getTrackName(String type) { if (mTrackList != null) { for (ListBean item : mTrackList) { if (item.getNum() != null && type != null && TextUtils.equals(item.getNum(), type)) { return item.getCom(); } } } return ""; } // 设置外部数据源 public void setTrackList(List<ListBean> list) { this.mTrackList = list; } // 缓存当前列表 @Override public void setNewInstance(List<ListBean> list) { super.setNewInstance(list); this.currentList = list; } // 获取所有开启提醒的条目 public List<ListBean> getRemindedItems() { List<ListBean> result = new ArrayList<>(); if (currentList == null) return result; Set<String> remindedNumbers = ReminderManager.getInstance(context).getRemindedNumbers(); for (ListBean bean : currentList) { if (remindedNumbers.contains(bean.getNum())) { result.add(bean); } } return result; } /** * 根据快递公司名称设置对应的 Logo 图标 */ private void setCompanyLogo(String name, ImageView logo, LinearLayout line, TextView text) { if (name == null || name.isEmpty()) { logo.setVisibility(View.GONE); line.setVisibility(View.VISIBLE); text.setText(name); return; } switch (name) { case "邮政快递包裹": logo.setImageResource(R.mipmap.img_yz_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "京东物流": logo.setImageResource(R.mipmap.img_jd_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "圆通快递": logo.setImageResource(R.mipmap.img_yt_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "中通快递": logo.setImageResource(R.mipmap.img_zt_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "顺丰速运": logo.setImageResource(R.mipmap.img_sf_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "韵达快递": logo.setImageResource(R.mipmap.img_yd_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "申通快递": logo.setImageResource(R.mipmap.img_st_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "EMS": logo.setImageResource(R.mipmap.img_ems_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; default: logo.setVisibility(View.GONE); line.setVisibility(View.VISIBLE); text.setText(name); break; } } private void showNotificationPermissionDialog() { if (context == null) return; new AlertDialog.Builder(context) .setTitle("需要通知权限") .setMessage("请允许本应用发送快递状态提醒通知。\n\n进入【设置】→【通知】中开启权限。") .setPositiveButton("去开启", (dialog, which) -> { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.fromParts("package", context.getPackageName(), null)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); }) .setNegativeButton("取消", (dialog, which) -> { Toast.makeText(context, "未授予通知权限,无法开启提醒", Toast.LENGTH_SHORT).show(); }) .create() .show(); } } 这个页面可以实现我开启提醒后,每次进入这个页面请求接口获取新的状态,根据新状态发送提醒吗
11-29
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值