
本文详细介绍了如何在android应用中,针对从服务器动态获取并展示的列表数据,实现新项目加入时的本地通知机制。核心策略是通过维护前后两次数据集合的对比,识别出真正的新增项,并利用android的notification api构建和发送通知,同时优化了数据获取和通知逻辑,避免重复通知。
在Android应用开发中,实时或准实时地从服务器获取数据并更新UI是常见需求。当数据以列表形式展示,并且列表内容频繁变动时,如何准确地识别出“新”添加的条目并向用户发送本地通知,是一个需要精心设计的环节。本教程将指导您如何实现这一功能,避免常见的逻辑错误,确保通知的准确性和用户体验。
问题的核心在于,当列表数据从服务器更新时,我们不能简单地通过列表大小的变化来判断是否有新项目。尤其是在列表有固定容量(例如30项,新项加入时旧项移除)的情况下,列表大小可能不变,但内容已发生变化。因此,我们需要一种更可靠的机制来识别真正的新增项。
关键在于为每个数据项(如Event对象)定义一个唯一标识符。在您的Event模型中,id字段非常适合作为这个标识符。通过比较新获取的数据集合与之前的数据集合中的id,我们可以精确地找出那些在旧数据中不存在的id所对应的新项目。
为了实现新项目的检测,我们需要在每次数据成功获取后执行以下步骤:
我们将基于您提供的EventsActivity和Event模型进行修改和扩展。
在EventsActivity中,我们需要一个成员变量来存储上一次获取到的事件列表。
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import butterknife.Bind;
import butterknife.ButterKnife;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
public class EventsActivity extends AppCompatActivity {
@Bind(R.id.back) View back;
@Bind(R.id.list) ListView list;
@Bind(R.id.clearAllEvents) View clearAllEvents;
@Bind(R.id.content_layout) View content_layout;
@Bind(R.id.loading_layout) View loading_layout;
@Bind(R.id.nodata_layout) View nodata_layout;
@Bind(R.id.search) View search;
String searchtext;
private EventsAdapter adapter;
private List<Event> previousEvents = new ArrayList<>(); // 用于存储上一次获取的事件列表
private Handler pollingHandler = new Handler(Looper.getMainLooper());
private static final long POLLING_INTERVAL_MS = 5000; // 每5秒刷新一次数据
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_events);
ButterKnife.bind(this);
adapter = new EventsAdapter(this);
list.setAdapter(adapter);
// 首次加载数据
fetchEvents();
}
@Override
protected void onResume() {
super.onResume();
// 当Activity可见时开始定时刷新数据
pollingHandler.post(fetchRunnable);
}
@Override
protected void onPause() {
super.onPause();
// 当Activity不可见时停止定时刷新
pollingHandler.removeCallbacks(fetchRunnable);
}
private Runnable fetchRunnable = new Runnable() {
@Override
public void run() {
fetchEvents();
pollingHandler.postDelayed(this, POLLING_INTERVAL_MS);
}
};
private void fetchEvents() {
final String api_key = (String) DataSaver.getInstance(EventsActivity.this).load("api_key");
loading_layout.setVisibility(View.VISIBLE);
API.getApiInterface(this).getEvents(api_key, getResources().getString(R.string.lang), 0, new Callback<ApiInterface.GetEventsResult>() {
@Override
public void success(ApiInterface.GetEventsResult result, Response response) {
loading_layout.setVisibility(View.GONE);
List<Event> currentEvents = result.items.data;
if (currentEvents != null && !currentEvents.isEmpty()) {
// 1. 检测并发送新事件通知
detectAndNotifyNewEvents(currentEvents);
// 2. 更新UI
adapter.setArray(new ArrayList<>(currentEvents)); // 传递副本,避免直接修改原始数据
content_layout.setVisibility(View.VISIBLE);
nodata_layout.setVisibility(View.GONE);
} else {
nodata_layout.setVisibility(View.VISIBLE);
content_layout.setVisibility(View.GONE);
adapter.setArray(new ArrayList<>()); // 清空适配器数据
}
// 3. 更新previousEvents为当前数据,以便下次对比
previousEvents = new ArrayList<>(currentEvents); // 存储副本
}
@Override
public void failure(RetrofitError retrofitError) {
loading_layout.setVisibility(View.GONE);
nodata_layout.setVisibility(View.VISIBLE);
content_layout.setVisibility(View.GONE);
Toast.makeText(EventsActivity.this, R.string.errorHappened, Toast.LENGTH_SHORT).show();
}
});
}
/**
* 检测新事件并发送通知
* @param currentEvents 当前从服务器获取的事件列表
*/
private void detectAndNotifyNewEvents(List<Event> currentEvents) {
// 首次加载时,不发送通知,只记录当前数据为旧数据
if (previousEvents.isEmpty()) {
return;
}
// 将旧事件的ID存入HashSet,以便高效查找
Set<Integer> previousEventIds = new HashSet<>();
for (Event event : previousEvents) {
previousEventIds.add(event.id);
}
// 遍历当前事件列表,查找新事件
for (Event newEvent : currentEvents) {
if (!previousEventIds.contains(newEvent.id)) {
// 发现新事件,发送通知
sendNotificationForNewEvent(newEvent);
}
}
}
/**
* 为新事件发送本地通知
* @param event 新事件对象
*/
private void sendNotificationForNewEvent(Event event) {
// 生成一个随机的通知ID,确保每次通知都是独立的
int notificationId = new Random().nextInt(100000);
String channelId = "new_event_channel";
String channelName = "新事件通知";
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// 为Android O (API 26) 及更高版本创建通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (notificationManager != null && notificationManager.getNotificationChannel(channelId) == null) {
NotificationChannel notificationChannel = new NotificationChannel(
channelId, channelName, NotificationManager.IMPORTANCE_HIGH
);
notificationChannel.setDescription("用于显示新事件的通知");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationManager.createNotificationChannel(notificationChannel);
}
}
// 构建点击通知后要启动的Intent
Intent intent = new Intent(this, EventsActivity.class);
// 可选:将事件ID传入,以便在Activity中高亮显示或定位该事件
intent.putExtra("highlight_event_id", event.id);
// 清除Activity栈,确保每次打开都是新的或顶部的Activity
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
// 创建PendingIntent,用于在通知被点击时触发
// 对于Android 12 (API 31) 及更高版本,PendingIntent必须声明可变性
int flags = PendingIntent.FLAG_UPDATE_CURRENT;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
flags |= PendingIntent.FLAG_IMMUTABLE;
}
PendingIntent pendingIntent = PendingIntent.getActivity(
getApplicationContext(),
notificationId, // 使用通知ID以上就是Android实时数据列表新增项通知机制实现指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号