我有一个从Realtime-Database (Firebase)获得wrapper in C# Firebase.Xamarin
的对象列表private List<Job> jobList = null;
首先填充应用程序,使用以下代码加载:
private async void PopulateList()
{
IReadOnlyCollection<Firebase.Xamarin.Database.FirebaseObject<Job>> items = await firebase
.Child("jobs")
.OnceAsync<Job>();
jobList = new List<Job>();
foreach (var item in items)
{
jobList.Add(
new Job
{
ID = item.Object.ID,
StartDate = item.Object.StartDate,
EndDate = item.Object.EndDate,
Description = item.Object.Description
});
}
SubscribeDbChanges();
}
我想订阅数据库以触发事件并将新对象更改/添加到列表中并触发事件后显示或通知用户一次,发生了更改。为此我使用了Observable,Reactive Rx.Net with All 通过以下方式:
private void SubscribeDbChanges()
{
Observable.All<FirebaseEvent<Job>>(
firebase
.Child("jobs")
.AsObservable<Job>(),
job => !jobList
.Contains(job.Object))
.Subscribe(jobItem =>
{
});
}
代码有什么问题吗?此外,我应该在哪里创建变更已到达的事件?
答案 0 :(得分:3)
首先我建议删除foreach/Add
,这是Select
private async void PopulateList()
{
jobList = (await firebase
.Child("jobs")
.OnceAsync<Job>())
.Select(item =>
new Job
{
ID = item.Object.ID,
StartDate = item.Object.StartDate,
EndDate = item.Object.EndDate,
Description = item.Object.Description
});
SubscribeDbChanges();
}
然后我会使用Where
。你如何使用All
很奇怪,它是一个扩展方法,你称之为通常的静态方法。这是可能的,但现在应该如何使用它。以下是包含Where
的代码:
private void SubscribeDbChanges()
{
firebase
.Child("jobs")
.AsObservable<Job>()
.Where(job => !jobList.Contains(job.Object))
.Subscribe(jobItem =>
{
});
}
答案 1 :(得分:1)
感谢@Alexey Zimarev给我一个快速点击,流畅的代码出现了: 首先采用ConcurrentDictionary作为数据成员并初始化 Firebaseclient ,然后填充列表;
FirebaseClient firebase;
private ConcurrentDictionary<string, Job> jobList ;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
firebase = new FirebaseClient("https://samplehosting-XXXX.firebaseio.com/");
PopulateList();
}
在这个函数中我初始化了字典并完成了 UI 工作,最后分别设置了监听器来监控 SubscribeToDbChanges
中的变化private async void PopulateList()
{
IReadOnlyCollection<Firebase.Xamarin.Database.FirebaseObject<Job>> items = await firebase
.Child("jobs")
.OnceAsync<Job>();
jobList = new ConcurrentDictionary<string, Job>();
foreach (var job in items)
{
while (!jobList.TryAdd(job.Object.ID, job.Object)) ;
}
list = FindViewById<ListView>(Resource.Id.listJobs);
list.ChoiceMode = ChoiceMode.Single;
HomeScreenAdapter ListAdapter = new HomeScreenAdapter(this, jobList);
list.Adapter = ListAdapter;
SubscribeToDbChanges();
}
在这里,我为字典中的键键设置插入观察者,而不是为设置删除观察者字典中可用的键。
private void SubscribeToDbChanges()
{
firebase
.Child("jobs").AsObservable<Job>()
.Where(job => !jobList.ContainsKey(job.Object.ID) && job.EventType == Firebase.Xamarin.Database.Streaming.FirebaseEventType.InsertOrUpdate)
.Subscribe(job =>
{
if (job.EventType == Firebase.Xamarin.Database.Streaming.FirebaseEventType.InsertOrUpdate)
{
while (!jobList.TryAdd(job.Object.ID, job.Object)) ;
}
});
firebase
.Child("jobs").AsObservable<Job>()
.Where(job => jobList.ContainsKey(job.Object.ID) && job.EventType == Firebase.Xamarin.Database.Streaming.FirebaseEventType.Delete)
.Subscribe(job =>
{
Thread remove = new Thread(() =>
{
Job removed = null;
jobList.TryRemove(job.Object.ID, out removed);
});
remove.Start();
});
}
PS:假设在这里,我假设我们在上面的问题和答案中添加的对象没有得到比较,因为存在存在。就像新对象被实例化一样,它可能与列表中已存在的克隆不同。如果我对Linq行为有误,请纠正我。但是上面给出的代码在我的场景中使用字典。