Android 用于通知管理的线程冲突观察者模式
我正在开发一个android应用程序,它必须接收一些通知。 我在firebase之间收到了这个通知,我创建了一个dispatcher对象来更新某些片段或活动中的一些信息Android 用于通知管理的线程冲突观察者模式,android,android-thread,Android,Android Thread,我正在开发一个android应用程序,它必须接收一些通知。 我在firebase之间收到了这个通知,我创建了一个dispatcher对象来更新某些片段或活动中的一些信息 2019-08-26 17:38:41.668 1193-1440/? W/InputDispatcher: channel 'd733762 it.myapp/it.myapp.Chat (server)' ~ Consumer closed input channel or an error occurred. even
2019-08-26 17:38:41.668 1193-1440/? W/InputDispatcher: channel 'd733762 it.myapp/it.myapp.Chat (server)' ~ Consumer closed input channel or an error occurred. events=0x9
2019-08-26 17:38:41.668 1193-1440/? E/InputDispatcher: channel 'd733762 it.myapp/it.myapp.Chat (server)' ~ Channel is unrecoverably broken and will be disposed!
2019-08-26 17:38:41.750 1193-2760/? I/WindowManager: WIN DEATH: Window{d733762 u0 it.myapp/it.myapp.Chat}
2019-08-26 17:38:41.750 1193-2760/? V/WindowManager: removeIfPossible: Window{d733762 u0 it.myapp/it.myapp.Chat}
2019-08-26 17:38:41.750 1193-2760/? W/InputDispatcher: Attempted to unregister already unregistered input channel 'd733762 it.myapp/it.myapp.Chat (server)'
2019-08-26 17:38:41.750 1193-2760/? V/WindowManager: Not removing Window{d733762 u0 it.myapp/it.myapp.Chat EXITING} due to exit animation
2019-08-26 17:38:41.772 1193-11657/? V/WindowManager: Exit animation finished in Window{d733762 u0 it.myapp/it.myapp.Chat EXITING}: remove=true
2019-08-26 17:38:41.773 1193-11657/? E/WindowManager: win=Window{d733762 u0 it.myapp/it.myapp.Chat EXITING} destroySurfaces: appStopped=false win.mWindowRemovalAllowed=true win.mRemoveOnExit=true
2019-08-26 17:38:41.773 1193-11657/? W/WindowManager: Exception thrown when updateSurfaceStatusSurface(name=it.myapp/it.myapp.Chat)/@0xafbd060: android.os.DeadObjectException
2019-08-26 17:38:41.774 1193-11657/? V/WindowManager: postWindowRemoveCleanupLocked: Window{d733762 u0 it.myapp/it.myapp.Chat}
2019-08-26 17:38:41.774 1193-11657/? V/WindowManager: Removing Window{d733762 u0 it.myapp/it.myapp.Chat} from AppWindowToken{74a1a5f token=Token{39042fe ActivityRecord{f6f3eb9 u0 it.myapp/.Chat t1826}}}
2019-08-26 17:38:41.782 1193-11657/? V/WindowManager: removeAppToken: AppWindowToken{74a1a5f token=Token{39042fe ActivityRecord{f6f3eb9 u0 it.myapp/.Chat t1826}}} delayed=true Callers=com.android.server.wm.DisplayContent.removeAppToken:1086 com.android.server.wm.AppWindowContainerController.removeContainer:315 com.android.server.am.ActivityRecord.removeWindowContainer:1201 com.android.server.am.ActivityStack.removeActivityFromHistoryLocked:4568
2019-08-26 17:38:41.817 2085-4155/? E/DollieAdapterService: notifyActivityState pkg:it.myapp/it.myapp.Chat state:18 fg:false mUid:10162
2019-08-26 17:38:41.817 1193-1299/? I/StatusBarDisable: setFlags what=0 which=1 pkg=Window{d733762 u0 it.myapp/it.myapp.Chat}
2019-08-26 17:38:41.817 1193-1299/? I/StatusBarDisable: setFlags what=0 which=1 pkg=Window{d733762 u0 it.myapp/it.myapp.Chat}
2019-08-26 17:38:41.818 1193-1299/? I/StatusBarDisable: setFlags what=0 which=1 pkg=Window{d733762 u0 it.myapp/it.myapp.Chat}
我正在尝试为这个pourpose使用观察者模式
我已经创建了一个名为Update的接口
public interface Updateable {
void update();
void update(int caller);
void update(int caller, Object obj);
}
片段或活动是观察者,并实现更新
notification dispatcher是主体,它存储可更新对象,并在FirebaseMessagingService向其传递通知时通知
我的问题是,当我可视化一个可更新的活动聊天时,我收到一个必须更新聊天的通知,我有一个线程冲突和崩溃
这是关于聊天活动的日志
2019-08-26 17:38:41.668 1193-1440/? W/InputDispatcher: channel 'd733762 it.myapp/it.myapp.Chat (server)' ~ Consumer closed input channel or an error occurred. events=0x9
2019-08-26 17:38:41.668 1193-1440/? E/InputDispatcher: channel 'd733762 it.myapp/it.myapp.Chat (server)' ~ Channel is unrecoverably broken and will be disposed!
2019-08-26 17:38:41.750 1193-2760/? I/WindowManager: WIN DEATH: Window{d733762 u0 it.myapp/it.myapp.Chat}
2019-08-26 17:38:41.750 1193-2760/? V/WindowManager: removeIfPossible: Window{d733762 u0 it.myapp/it.myapp.Chat}
2019-08-26 17:38:41.750 1193-2760/? W/InputDispatcher: Attempted to unregister already unregistered input channel 'd733762 it.myapp/it.myapp.Chat (server)'
2019-08-26 17:38:41.750 1193-2760/? V/WindowManager: Not removing Window{d733762 u0 it.myapp/it.myapp.Chat EXITING} due to exit animation
2019-08-26 17:38:41.772 1193-11657/? V/WindowManager: Exit animation finished in Window{d733762 u0 it.myapp/it.myapp.Chat EXITING}: remove=true
2019-08-26 17:38:41.773 1193-11657/? E/WindowManager: win=Window{d733762 u0 it.myapp/it.myapp.Chat EXITING} destroySurfaces: appStopped=false win.mWindowRemovalAllowed=true win.mRemoveOnExit=true
2019-08-26 17:38:41.773 1193-11657/? W/WindowManager: Exception thrown when updateSurfaceStatusSurface(name=it.myapp/it.myapp.Chat)/@0xafbd060: android.os.DeadObjectException
2019-08-26 17:38:41.774 1193-11657/? V/WindowManager: postWindowRemoveCleanupLocked: Window{d733762 u0 it.myapp/it.myapp.Chat}
2019-08-26 17:38:41.774 1193-11657/? V/WindowManager: Removing Window{d733762 u0 it.myapp/it.myapp.Chat} from AppWindowToken{74a1a5f token=Token{39042fe ActivityRecord{f6f3eb9 u0 it.myapp/.Chat t1826}}}
2019-08-26 17:38:41.782 1193-11657/? V/WindowManager: removeAppToken: AppWindowToken{74a1a5f token=Token{39042fe ActivityRecord{f6f3eb9 u0 it.myapp/.Chat t1826}}} delayed=true Callers=com.android.server.wm.DisplayContent.removeAppToken:1086 com.android.server.wm.AppWindowContainerController.removeContainer:315 com.android.server.am.ActivityRecord.removeWindowContainer:1201 com.android.server.am.ActivityStack.removeActivityFromHistoryLocked:4568
2019-08-26 17:38:41.817 2085-4155/? E/DollieAdapterService: notifyActivityState pkg:it.myapp/it.myapp.Chat state:18 fg:false mUid:10162
2019-08-26 17:38:41.817 1193-1299/? I/StatusBarDisable: setFlags what=0 which=1 pkg=Window{d733762 u0 it.myapp/it.myapp.Chat}
2019-08-26 17:38:41.817 1193-1299/? I/StatusBarDisable: setFlags what=0 which=1 pkg=Window{d733762 u0 it.myapp/it.myapp.Chat}
2019-08-26 17:38:41.818 1193-1299/? I/StatusBarDisable: setFlags what=0 which=1 pkg=Window{d733762 u0 it.myapp/it.myapp.Chat}
这是聊天活动
该类是为发送通知而创建的另一个静态类
public class NotificationEventDispatcher {
private static HashMap<Integer, ArrayList<RegisteredUpdt>> listOfUpdateable = new HashMap<>();
private static final Integer NUM_CHANNEL = 3;
private static final Integer MIN_CH = 0;
private static final Integer MAX_CH = 2;
public static final Integer CH_0 = 0;
public static final Integer CH_1 = 1;
public static final Integer CH_2 = 2;
private NotificationEventDispatcher(){}
public static boolean registry(Integer key, Updateable obj, Integer channel){
if(channel < MIN_CH || channel > MAX_CH){
Log.d(TAG, "channel out of range");
return false;
}
else{
if(!listOfUpdateable.containsKey(channel))
listOfUpdateable.put(channel, new ArrayList<RegisteredUpdt>());
ArrayList<RegisteredUpdt> regUpArray = listOfUpdateable.get(channel);
RegisteredUpdt reg = new RegisteredUpdt(obj, key);
if(regUpArray.contains(reg)){
regUpArray.set(regUpArray.indexOf(reg),reg);
return false;
}
else{
regUpArray = listOfUpdateable.get(channel);
regUpArray.add(reg);
return true;
}
}
}
public static boolean unregister(Integer key, Updateable obj, Integer channel){
RegisteredUpdt reg = new RegisteredUpdt(obj, channel);
ArrayList<RegisteredUpdt> list = listOfUpdateable.get(channel);
if(!list.contains(reg))
return false;
else{
list.remove(list.indexOf(reg));
return true;
}
}
public static void dispatch(RemoteMessage rm){
if(rm.getData().containsKey("type")){
int type = Integer.parseInt(rm.getData().get("type"));
switch (type){
case 0:{
performCall(listOfUpdateable.get(NotificationEventDispatcher.CH_0), rm);
break;
}
case 1:{
performCall(listOfUpdateable.get(NotificationEventDispatcher.CH_1), rm);
break;
}
case 2:{
performCall(listOfUpdateable.get(NotificationEventDispatcher.CH_2), rm);
break;
}
}
}
}
private static void performCall(ArrayList<RegisteredUpdt> upt, RemoteMessage rm){
for(RegisteredUpdt reg:upt){
reg.getUp().update(reg.getUpdatekey(), rm);
}
}
private static class RegisteredUpdt{
private Updateable up;
private int updatekey;
public RegisteredUpdt(Updateable up, int updatekey) {
this.up = up;
this.updatekey = updatekey;
}
public Updateable getUp() {
return up;
}
public void setUp(Updateable up) {
this.up = up;
}
public int getUpdatekey() {
return updatekey;
}
public void setUpdatekey(int updatekey) {
this.updatekey = updatekey;
}
@Override
public boolean equals(Object obj) {
return (((RegisteredUpdt)obj).getUpdatekey() == this.updatekey);
}
}
}
这是一个非常不寻常的问题,我真的不知道如何在不破坏观察器架构的情况下修复它
每一条建议都是有价值的。
谢谢。发布FirebaseMessagingService的代码。。。但无论如何,我不认为使用一个临时可观察的实现在服务和活动之间进行通信是可行的。相反,您应该查看LocalBroadcastManagerI,添加firebase通知服务和通知Dispatcher。我读到了LocalBroadcasatManager,它是管理此类更新的更好方法。如果你能帮我解决这个问题,我将不胜感激。该应用程序是用于学校用途的,我不想在这一点上重新开始。非常感谢。我将采取一些步骤来了解问题的原因。1注释掉public void run{}中的所有内容,并检查它是否崩溃。2如果没有崩溃,请编辑您的答案并在此处添加以下文件:RemoteMessage、Message和ChatAdapter。我会检查他们是否是问题的根源。同时告诉我你的设备和Android版本。
public class NotificationEventDispatcher {
private static HashMap<Integer, ArrayList<RegisteredUpdt>> listOfUpdateable = new HashMap<>();
private static final Integer NUM_CHANNEL = 3;
private static final Integer MIN_CH = 0;
private static final Integer MAX_CH = 2;
public static final Integer CH_0 = 0;
public static final Integer CH_1 = 1;
public static final Integer CH_2 = 2;
private NotificationEventDispatcher(){}
public static boolean registry(Integer key, Updateable obj, Integer channel){
if(channel < MIN_CH || channel > MAX_CH){
Log.d(TAG, "channel out of range");
return false;
}
else{
if(!listOfUpdateable.containsKey(channel))
listOfUpdateable.put(channel, new ArrayList<RegisteredUpdt>());
ArrayList<RegisteredUpdt> regUpArray = listOfUpdateable.get(channel);
RegisteredUpdt reg = new RegisteredUpdt(obj, key);
if(regUpArray.contains(reg)){
regUpArray.set(regUpArray.indexOf(reg),reg);
return false;
}
else{
regUpArray = listOfUpdateable.get(channel);
regUpArray.add(reg);
return true;
}
}
}
public static boolean unregister(Integer key, Updateable obj, Integer channel){
RegisteredUpdt reg = new RegisteredUpdt(obj, channel);
ArrayList<RegisteredUpdt> list = listOfUpdateable.get(channel);
if(!list.contains(reg))
return false;
else{
list.remove(list.indexOf(reg));
return true;
}
}
public static void dispatch(RemoteMessage rm){
if(rm.getData().containsKey("type")){
int type = Integer.parseInt(rm.getData().get("type"));
switch (type){
case 0:{
performCall(listOfUpdateable.get(NotificationEventDispatcher.CH_0), rm);
break;
}
case 1:{
performCall(listOfUpdateable.get(NotificationEventDispatcher.CH_1), rm);
break;
}
case 2:{
performCall(listOfUpdateable.get(NotificationEventDispatcher.CH_2), rm);
break;
}
}
}
}
private static void performCall(ArrayList<RegisteredUpdt> upt, RemoteMessage rm){
for(RegisteredUpdt reg:upt){
reg.getUp().update(reg.getUpdatekey(), rm);
}
}
private static class RegisteredUpdt{
private Updateable up;
private int updatekey;
public RegisteredUpdt(Updateable up, int updatekey) {
this.up = up;
this.updatekey = updatekey;
}
public Updateable getUp() {
return up;
}
public void setUp(Updateable up) {
this.up = up;
}
public int getUpdatekey() {
return updatekey;
}
public void setUpdatekey(int updatekey) {
this.updatekey = updatekey;
}
@Override
public boolean equals(Object obj) {
return (((RegisteredUpdt)obj).getUpdatekey() == this.updatekey);
}
}
}