I'm doing a long write operation, sending 16 byte batches at a time. I'd like to have a progress bar show the progress of the long write to the user, so I need some sort of callback for each time a batch has been written.
From the documentation, it looked like setWriteOperationAckStrategy does this. However, when running the following code, I only end up seeing one message output to the log. What am I doing wrong here?
subscription = connection.flatMap(rxBleConnection -> rxBleConnection.createNewLongWriteBuilder()
.setCharacteristicUuid(uuid)
.setBytes(bytes)
.setMaxBatchSize(16)
.setWriteOperationAckStrategy(new RxBleConnection.WriteOperationAckStrategy() {
#Override
public Observable<Boolean> call(Observable<Boolean> booleanObservable) {
Log.d("TEST", "batch written");
return booleanObservable;
}
})
.build()
The setWriteOperationAckStrategy is similar to standard RxJava's Observable transformers. In order to keep the allocation low, we tend to modify source observable rather than to create a new one when each batch is completed.
subscription = connection.flatMap(rxBleConnection -> rxBleConnection.createNewLongWriteBuilder()
.setCharacteristicUuid(uuid)
.setBytes(bytes)
.setMaxBatchSize(16)
.setWriteOperationAckStrategy(new RxBleConnection.WriteOperationAckStrategy() {
#Override
public Observable<Boolean> call(Observable<Boolean> booleanObservable) {
Log.d("TEST", "batch written");
return booleanObservable
.doOnNext(new Action1<Boolean>() {
#Override
public void call(Boolean aBoolean) {
Log.d("TEST", "batch written");
}
});
}
})
.build()
I think this answer was for RxJava, for RxJava2 this is the updated lambda syntax:
.setWriteOperationAckStrategy(booleanObservable -> {
Log.d("TEST", "batch written");
return booleanObservable
.doOnNext(aBoolean -> {
Log.d("TEST", "batch written");
});
}
Full:
.setWriteOperationAckStrategy(new RxBleConnection.WriteOperationAckStrategy() {
#Override
public Observable<Boolean> apply(Observable<Boolean> booleanObservable) {
Log.d("TEST", "batch written");
return booleanObservable
.doOnNext(new Consumer<Boolean>() {
#Override
public void accept(Boolean aBoolean) {
Log.d("TEST", "batch written");
}
});
}
Related
how to access the id which a map inside an array which inside another array?
I have attached firestore structure here
db structure in firestore
this is my code.. im using two where conditions here as you can see, you have to go to the refrence of that collection and add .where("fieldnameinfirestore", "yourvalue")..
private void GetCityListsnames() {
db.collection("citylist").document("city").
collection(uservolcity).whereEqualTo("complete","false").
whereEqualTo("takebyvol","false")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
mlistsproper.add(new VolListProperDataModel(document.getId(),document.getString("listname"),
document.getString("sendinguserphone"),
document.getString("sendingusername"),
document.getString("deliveryaddress"),uservolcity));
}
if(mlistsproper.size() == 0){
nolist.setVisibility(View.VISIBLE);
}
progressBar.setVisibility(View.INVISIBLE);
mAdapter.notifyDataSetChanged();
GetAccptListsnames();
} else {
Log.d("Errorgeetingaddres", "Error getting documents: ", task.getException());
Toast.makeText(getActivity().getApplicationContext(),
"Make sure you have added delivery address", Toast.LENGTH_SHORT).show();
}
}
});
}
In you success listner of firestore request you can get the array like this!
List<String> group = (List<String>) document.get("arrayfieldname");
Is there an example of how to create a GlobalKTable to keep count from a KStream using Spring Cloud stream and using Functional approach?
Is implementing processor interface the right approach?
#Bean
public Consumer<KStream<String, Long>> processorsample() {
return input -> input.process(() -> new Processor<String, Long>() {
#Override
public void init(ProcessorContext context) {
if (state == null) {
state = (KeyValueStore<String, Long>) context.getStateStore("mystate");
}
}
#Override
public void process(String key, Long value) {
if (state != null) {
if (key != null) {
Long currentCount = state.get(key);
if (currentCount == null) {
state.put(key, value);
} else {
state.put(key, currentCount + value);
}
}
}
}
#Override
public void close() {
if (state != null) {
state.close();
}
}
}, "mystate");
}
According to the documentation GlobalKTables are read-only, you cannot modify a global table during the processing.
Since GlobalKTables are consumers of a Kafka topic, you can just send your data to the GlobalKTable's source topic, and eventually, it's going to be added to the table. But you cannot be sure that the GlobalKTable will be updated immediately.
Here is the Code and where i am sending request to fetching the data and first time it is loading fast and when i am coming back from anuyother page then this page is taking too much time that too when i am using Device.BeginInvokeOnMainThread() within Task.Run().
==============================================================================
public Home()
{
if (HomeModel.GetInstance().GetHomeDataPopulate())
{
FireContentPageInitialized();
}
else
{
CallRequest();
}
}
private async void CallRequest()
{
await Task.Run(async () =>
{
await Task.Delay(3000);
SetBannerData();
SetBrandsData();
SetHotDealsData();
SetNewlyAddedData();
SetRecentlyViewed();
SetRecentlyPurchased();
});
}
//Sending Requests to fetching data in subscribed events...
private void SetBannerData()
{
ModelController.OnGetHomeBannerDataSuccess += ModelController_OnGetHomeBannerDataSuccess;
ModelController.OnGetHomeBannerDataFailure += ModelController_OnGetHomeBannerDataFailure;
ModelController.FetchBannerData();
}
//Fetching Data and binding with UI Itemsource...
private void ModelController_OnGetHomeBannerDataSuccess(object sender, CustomEventArgs eventArgs)
{
stackBanner.ItemsSource = null;
stackBanner.ItemsSource = HomeModel.GetInstance().GetHomeBanners();
}
==============================================================================
This is my Code..and i added comment line where i am binding UI. I can't add lots of code here because it's too lengthy so i have added only one method which is binding UI and other methods are also doing the same.
You are trying to update view by another thread. To update view created by main thread from another thread you must do something like this. Example pseudo code (I don't know your methods).
await Task.Run(() => {
try
{
Device.BeginInvokeOnMainThread(() =>
{
SetBannerData();
SetBrandsData();
SetHotDealsData();
SetNewlyAddedData();
SetRecentlyViewed();
SetRecentlyPurchased();
}
}
catch (Exception ex)
{
}
I have xamarin.forms app contains a listview which will load values from Rest API.Which is working fine.I have button just above the listview.When I click on the button, the listview API call will be placed again and the listview should update. But stuck at this update part.I am not using MVVM pattern.The listview listing portion is an async Task.I am calling the async task again when the button click, but App gets crash. Is it due to calling the async task again from button click? Any help is appreciated.
Here is My code.
namespace app
{
public partial class List : ContentPage
{
PendingWeekRange pendingWeekRange = new PendingWeekRange();
public TimeSheetList()
{
InitializeComponent();
Task.Run(async () =>
{
await LoadScreenItems();
});
}
async Task LoadScreenItems()
{
await Task.Run(async () => {
try
{
// Doing some stuff
await loadTimeSheetList();
}
catch (Exception)
{
}
});
}
async Task loadTimeSheetList()
{
await Task.Run(() => { + string postdataForPendingList = "{\"date\":\"" + "1" + "\"}";
APICall callForAPICallResult = new APICall("/API/ListMobile/ListForApproval", postdataForList, loadingIndicator);
try
{
List<ListData> resultObjForPendingTimeSheetList = callForAPICallResult<List<ListData>>();
if (resultObjForPendingTimeSheetList != null)
{
TimesheetList.ItemsSource = resultObjForPendingTimeSheetList;
screenStackLayout.VerticalOptions = LayoutOptions.FillAndExpand;
TimesheetList.IsVisible = true;
}
else
{
}
}
catch (Exception)
{
}
});
}
async void Button_Tapped(object sender, EventArgs e)
{
try
{
// Calling my listview again. After calling app gets crash
Task.Run(async () => await loadTimeSheetList());
}
catch (Exception ex) { }
}
}
}
A few things before getting to the problem. You've got async/await all wrong, go though Async Programming
Task.Run runs the passed action on a different thread, if you make changes to UI elements on this thread, your app will definitely(take my word) crash.
If you want to make async call at page launch, make use of OnAppearing method (if you only want to call once, maintain a flag)
Do not change the ItemsSource of a list view frequently, just clear and add items to it.
namespace app
{
public partial class List : ContentPage
{
PendingWeekRange pendingWeekRange = new PendingWeekRange();
private ObservableCollection<ListData> TimesheetObservableCollection = new ObservableCollection<ListData>();
public TimeSheetList()
{
InitializeComponent();
TimesheetList.ItemsSource = TimesheetObservableCollection;
}
protected override async OnAppearing()
{
// flag for first launch?
await LoadScreenItems();
}
async Task LoadScreenItems()
{
try
{
// Doing some stuff
TimesheetObservableCollection.Clear();
TimesheetObservableCollection.AddRange(await GetTimeSheetList());
}
catch (Exception)
{
//handle exception
}
}
async Task<List<ListData>> GetTimeSheetList()
{
string postdataForPendingList = "{\"date\":\"" + "1" + "\"}";
APICall callForAPICallResult = new APICall("/API/ListMobile/ListForApproval", postdataForList, loadingIndicator);
try
{
return callForAPICallResult<List<ListData>>();
}
catch (Exception)
{
// handle exception
}
}
async void Button_Tapped(object sender, EventArgs e)
{
try
{
// Calling my listview again. After calling app gets crash
TimesheetObservableCollection.Clear();
TimesheetObservableCollection.AddRange(await GetTimeSheetList());
}
catch (Exception ex) { }
}
}
}
#Androdevil,
Update your loadTimeSheetList with this,
async Task loadTimeSheetList()
{
try
{
// I am calling my API for Listview here.
List<TimeSheetListData> resultObjForPendingTimeSheetList = await callForPendingTimeSheetList.APICallResult<List<TimeSheetListData>>();
if (resultObjForPendingTimeSheetList != null)
{
TimesheetList.ItemsSource = resultObjForPendingTimeSheetList;
screenStackLayout.VerticalOptions = LayoutOptions.FillAndExpand;
TimesheetList.IsVisible = true;
}
else
{
}
}
catch (Exception)
{
}
}
I am implementing a simple data analytic functionality with RXJava, where a topic subscriber asynchronously processes the data published to a topic, depositing the output to the Redis.
When a message is received, the Spring component publishes it to an Observable. To avoid blocking the submission I used the RxJava Async to do this asynchronously.
#Override
public void onMessage(final TransactionalMessage message) {
Async.start(new Func0<Void>() {
#Override
public Void call() {
analyser.process(message);
return null;
}
});
}
I have two confusions in implementing other processing parts; 1) creating an asynchronous Observable with buffering 2) Computing different logics in parallel based on message type on list of messages.
After long experiments I found two ways to create the Async Observable and not sure which one is the right and better approach.
Way one,
private static final class Analyzer {
private Subscriber<? super TransactionalMessage> subscriber;
public Analyzer() {
OnSubscribe<TransactionalMessage> f = subscriber -> this.subscriber = subscriber;
Observable.create(f).observeOn(Schedulers.computation())
.buffer(5, TimeUnit.SECONDS, 5, Schedulers.io())
.skipWhile((list) -> list == null || list.isEmpty())
.subscribe(t -> compute(t));
}
public void process(TransactionalMessage message) {
subscriber.onNext(message);
}
}
Way two
private static final class Analyser {
private PublishSubject<TransactionalMessage> subject;
public Analyser() {
subject = PublishSubject.create();
Observable<List<TransactionalMessage>> observable = subject
.buffer(5, TimeUnit.SECONDS, 5, Schedulers.io())
.observeOn(Schedulers.computation());
observable.subscribe(new Observer<List<TransactionalMessage>>() {
#Override
public void onCompleted() {
log.debug("[Analyser] onCompleted(), completed!");
}
#Override
public void onError(Throwable e) {
log.error("[Analyser] onError(), exception, ", e);
}
#Override
public void onNext(List<TransactionalMessage> t) {
compute(t);
}
});
}
public void process(TransactionalMessage message) {
subject.onNext(message);
}
}
The TransactionalMessage comes in different types, so I want to perform different computations based on the types. One approach I tried is filter the list based on every type and process them separately, but this looks so bad and I think does not work in parallel. What way to process them in parallel?
protected void compute(List<TransactionalMessage> messages) {
Observable<TransactionalMessage> observable = Observable
.from(messages);
Observable<String> observable2 = observable
.filter(new Func1<TransactionalMessage, Boolean>() {
#Override
public Boolean call(TransactionalMessage t) {
return t.getMsgType()
.equals(OttMessageType.click.name());
}
}).flatMap(
new Func1<TransactionalMessage, Observable<String>>() {
#Override
public Observable<String> call(
TransactionalMessage t) {
return Observable.just(
t.getMsgType() + t.getAppId());
}
});
Observable<String> observable3 = observable
.filter(new Func1<TransactionalMessage, Boolean>() {
#Override
public Boolean call(TransactionalMessage t) {
return t.getMsgType()
.equals(OttMessageType.image.name());
}
}).flatMap(
new Func1<TransactionalMessage, Observable<String>>() {
#Override
public Observable<String> call(
TransactionalMessage t) {
return Observable.just(
t.getMsgType() + t.getAppId());
}
});
// I sense some code smell in filtering on type and processing it.
Observable.merge(observable2, observable3)
.subscribe(new Action1<String>() {
#Override
public void call(String t) {
// save it to redis
System.out.println(t);
}
});
}
I suggest thinking about Subjects before attempting to use create.
If you want parallel processing done based on some categorization, you could use groupBy along with observeOn to achieve the desired effect:
Observable.range(1, 100)
.groupBy(v -> v % 3)
.flatMap(g ->
g.observeOn(Schedulers.computation())
.reduce(0, (a, b) -> a + b)
.map(v -> g.getKey() + ": " + v)
)
.toBlocking().forEach(System.out::println);