Android 导致mutableData.setValue()的递归导致在backstack中生成相同的活动?
编辑:2016年10月23日:这一问题尚未解决,我仍在寻找答案。我将重写这个问题,使它更清楚,因为我现在知道是什么导致了这个问题Android 导致mutableData.setValue()的递归导致在backstack中生成相同的活动?,android,firebase,firebase-realtime-database,Android,Firebase,Firebase Realtime Database,编辑:2016年10月23日:这一问题尚未解决,我仍在寻找答案。我将重写这个问题,使它更清楚,因为我现在知道是什么导致了这个问题 编辑:2016年10月26日:发现了一些东西:在试图查找问题时,我发现了一个bug,它帮助我找到了一些东西。如果我的Firebase数据库中有以下内容: Campaigns{ UNQ_KEY: 1 //This is being set in the transaction } 而不是这: Campaigns{ UNQ_KEY:{ count:
编辑:2016年10月26日:发现了一些东西:在试图查找问题时,我发现了一个bug,它帮助我找到了一些东西。如果我的Firebase数据库中有以下内容:
Campaigns{
UNQ_KEY: 1 //This is being set in the transaction
}
而不是这:
Campaigns{
UNQ_KEY:{
count: 1 //this is being set in the transaction
}
}
问题没有发生
总之,这可能是一个递归错误
我有这个Firebase事务:
database.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
Long preUserIncrementedInt = Long.parseLong(b.getText().toString());
Long userIncrementedInt = ++preUserIncrementedInt;
mutableData.child("users").child(getUid()).child("count").setValue(userIncrementedInt);
Long preIncrementedTotalCount = mutableData.child("count").getValue(Long.class);
Long incrementedTotalCount = ++preIncrementedTotalCount;
mutableData.child("count").setValue(incrementedTotalCount);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
if (databaseError != null)
Log.wtf(TAG,databaseError.getMessage());
}
});
此行:
mutableData.child("users").child(getUid()).child("count").setValue(userIncrementedInt);
mutableData.child("count").setValue(incrementedTotalCount);
还有这个:
mutableData.child("users").child(getUid()).child("count").setValue(userIncrementedInt);
mutableData.child("count").setValue(incrementedTotalCount);
当我运行事务时,会再次创建并打开相同的活动。单击“后退”按钮时,它将转到“后退”中的上一个活动。但是,backback中的前一个活动本身就是相同的活动。像这样:
每次单击按钮时,backbackback中都会生成一个新的活动(有问题的活动)
为了向您展示它的外观,这里有一个GIF:
为什么会发生这种情况?它会重新启动您的活动,因为它在某处崩溃。请尝试以下代码:
public void onClick(View v) {
if (mp == null){
mp = new MediaPlayer();
} else {
mp.reset();
}
try {
AssetFileDescriptor afd;
afd = getAssets().openFd("click.mp3");
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mp.prepare();
mp.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e){
} catch (IOException e){
} catch (Exception e){
}
v.setEnabled(false);
final View clicked = v;
Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
clicked.setEnabled(true);
}
};
handler.postAtTime(runnable,System.currentTimeMillis()+100);
handler.postDelayed(runnable,100);
}
(我将在这里发布,因为它更容易管理我的评论)
未找到解决方案。
*更新4:找到解决方案** 经过多次尝试和大量注释,最终找到了解决方案,显然OP在另一个类中使用了增量方法,并将其移动到用于解决问题的同一个类中 至于为什么会发生这种情况,在我看来,可能与事务的并发性问题有关,可能问题在于它自己在创建一个循环。活动开始后,您实例化了
FirebaseController
,该控制器在某个时候触发了increment
方法,进行异步执行,最终(以某种方式失败?)再次启动活动
有关失败(但故障排除步骤)的尝试,请参见下文
我试着调试。在这些线路上都没有激活。需要 我需要一堆Android文件(比如View.java)。当我跑向 游标“(跳过下一个调试断点),它将重新启动 是否可以尝试检查runnable中单击的视图是否为空
Runnable runnable = new Runnable() {
@Override
public void run() {
// if not null do this
clicked.setEnabled(true);
// if null print some log
// ...
}
};
调试时是否使用单步执行或单步执行(如果您深入了解可能使用单步执行(F5)的类的层次结构,是否可以尝试使用单步执行(F6)进行调试)
如果我们找到了答案,我将在这里发布:
更新1:
mutableData.child("users").child(getUid()).child("count").setValue(userIncrementedInt);
mutableData.child("count").setValue(incrementedTotalCount);
MutableData#setValue(java.lang.Object)
说明了这是如何工作的:
将此位置的数据设置为给定值。本地类型
此方法接受对应于JSON类型的值:
Boolean
Long
Double
Map
列表
此外,您可以将自己类的实例设置到此位置,前提是它们满足以下约束:
该类必须具有不接受参数的默认构造函数
类必须为要分配的属性定义公共getter。
没有公共getter的属性将设置为其默认值
当实例被反序列化时
尝试使用其他开发人员建议的其他数据类型:
将#setValue
参数更改为上面列表中的一个对象,并返回一个对象,尝试强制转换为正确的类型,也许可以使用Integer
类
更新2:
您的数据模式是这样的吗
{
"campaings": {
"key": {
"count": "1",
"users": {
"-JRHTHaIs-jNPLXOQivY": {
"count": "1",
...
},
...
}
...
},
"other-key": {
...
}
...
}
}
这就是我从那里的代码片段推断的,如果我犯了错误,你可以澄清我
// here we are searching for the current reference in Campaings/key
DatabaseReference database = FirebaseDatabase.getInstance().getReference().child("Campaigns").child(key);
int preIncrementUserCount = Integer.parseInt(button.getText().toString());
final int incrementedUserCount = ++preIncrementUserCount;
button.setText(String.valueOf(incrementedUserCount));
database.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
// here we are searching for the current count value in
// Campaings/key/count
Integer currentValue = mutableData.child("count").getValue(Integer.class);
if (currentValue == null) {
// do something...
} else {
// here we are setting the count value in Campaings/key/count
mutableData.child("count").setValue(++currentValue);
}
// here we are setting the count value in Campaings/key/users/UUID/count
mutableData.child("users").child(getUid()).child("count").setValue(incrementedUserCount);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean committed, DataSnapshot dataSnapshot) {
if (databaseError != null) {
Log.e(TAG, "Error: " + databaseError.getMessage());
}
System.out.println("Transaction completed");
}
});
代码示例的要点是说明您正在执行的数据架构搜索(同样,如果我犯了错误,请在任何部分更正我),但出于调试目的,请将databaseError
登录到onComplete
更新3
从:
doTransaction()将被多次调用,并且必须能够
处理空数据。即使远程计算机中存在数据
数据库,当事务运行时,它可能不会在本地缓存
他跑了
尝试更改此部分:
if (currentValue == null) {
// do something...
} else {
// here we are setting the count value in Campaings/key/count
mutableData.child("count").setValue(++currentValue);
}
例如:
if (mutableData.child("count").getValue() == null) {
// print something...
// Log.d(TAG,"Value at some point was null");
// or maybe (just to test)
// mutableData.child("count").setValue(1);
} else {
// here we are setting the count value in Campaings/key/count
mutableData.child("count").setValue(++currentValue);
}
p.S:如果在可预见的未来有任何人可能会对类似的问题进行故障排除,我将离开解决方案可能是它试图启动未经准备的mediaplayer。这样开始:
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener(){
public void onPrepared(MediaPlayer p){
p.start();
}
}
编辑:
mutableData.child("users").child(getUid()).child("count").setValue(userIncrementedInt);
mutableData.child("count").setValue(incrementedTotalCount);
看看Firebase MutableData setValue(..)方法,它只接受以下类型。但是你使用int,它是基本类型
- 布尔值
- 长的
- 双重的
- 地图
- 名单
int totalCount = mutableData.child("count").getValue(int.class);
与
在这方面,
mutableData.child("count").setValue(newTotalCount);
int totalCount = mutableData.child("count").getValue(int.class);
您正在通过setValue()方法传递一个“int”值。它应该是此方法支持的对象
,
您正在通过“int.class”获得价值。它不是一个物体。它也应该是一个对象。改变这个。我希望它能帮助你。我们能看看活动代码的其余部分吗?@BlackHatSamurai当然可以。只是想确定这不是一个小错误,所以我没有提供完整的代码。给我一个sec@AbAppletic它是否给出任何错误跟踪?或者它只是重新启动而没有任何抱怨?您可以尝试捕获异常并打印它吗?也许是一些错误,而不是在那些3@IvanAlburquerque没有什么。重新启动。完整代码:你能解释一下这有什么不同吗?当我删除所有的
MediaPlayer
东西时,问题仍然存在。奇怪的是,这就解决了。但是,当我调用一个方法(增量)时,它也会重新启动。我会编辑我的问题请通过新的