How to use callback in flutter for background location - flutter

I am following this plugin (learning) background locator . I have previously used other background location plugins but they are not maintained anymore.
I am following the tutorial as described in the description of the plugin and so far this is my code.
I am unsure about what exactly a callback is and how do I use it.
This is my code so far but I don't get any results.
static void backgroundLocationCallBack(LocationDto location) async {
await BackgroundLocator.initialize();
await BackgroundLocator.isServiceRunning();
}
void getLocationLiveUpdates() async {
return await BackgroundLocator.registerLocationUpdate(
backgroundLocationCallBack,
autoStop: false,
// disposeCallback: backgroundLocationDisposeCallBack,
androidSettings: AndroidSettings(
accuracy: LocationAccuracy.NAVIGATION,
interval: 5,
distanceFilter: 0,
client: LocationClient.google,
androidNotificationSettings: AndroidNotificationSettings(
notificationChannelName: 'Location tracking',
notificationTitle: 'Start Location Tracking',
notificationMsg: 'Track location in background',
notificationBigMsg:
'Background location is on to keep the app up-tp-date with your location. This is required for main features to work properly when the app is not running.',
notificationIconColor: Colors.grey,
)));
}

Callbacks are used to perform some actions during certain events.
Here, the callback attribute takes backgroundLocationCallBack as its value, and as per the package code, it is used for performing appropriate actions when the LocationDto is available. This LocationDto object will contain the Location information you are looking for, and you can use it according to your use-case.
Similarly, disposeCallback is used to perform certain actions when dispose is called on the BackgroundLocator object. You can do something like close all the Ports that were opened for fetching the location.
There are other callbacks as well such as initCallback and initDataCallback which are used for setting the callbacks to initialise various parameters for your location service and to provide an initial data for the params respectively.

Related

Where to call reset method for RTKQ useMutation()?

Since RTK 1.7.0, mutation result object has a reset() method to unsubscribe from the state update of a mutation from another component:
const [mutate, { isLoading, reset }] = useMutation({ fixedCacheKey });
I use it to get isLoading state from another component's mutation. But I don't know where to call the cleanup reset():
In the click handler:
await mutate()
reset()
Or in the cleanup
useEffect(() => () => reset(), [reset])
If it's this case, then do I need to do this for both (original and subscriber) components? And this is weird: the identity of reset function changes after state update, so the isLoading is cleared right after it changes.
I think the docs about this function is not very clear. Hope someone can improve it.
I'm using React 17.0.2, RTK 1.7.1.
Mutations never share state between usage in different components in the fist place - unless you force that by using fixedCacheKey. Are you maybe trying to solve a non-problem here?

Instance method can't be accessed from static method

I have a boolean bool isDriverAvailable=false which will check if the user is online or not, if it is online then the GeoFire plugin will update its latitude and longitude to the database.
I am using a background location for this project which has a callback
static void backgroundLocationCallBack(LocationDto location) method where I plan to implement this check and update the location.
this is my code so far
class _HomeTabPageState extends State<HomeTabPage>
with AutomaticKeepAliveClientMixin, OSMMixinObserver {
bool isDriverAvailable = false;
//some code
static void backgroundLocationCallBack(LocationDto location) async {
print("from background location +${location.latitude}");
if (isDriverAvailable)
Geofire.setLocation(
currentFirebaseUser!.uid, location.latitude!, location.longitude!);
}
void getLocationLiveUpdates() async {
return await BackgroundLocator.registerLocationUpdate(
backgroundLocationCallBack,
autoStop: false,
// disposeCallback: backgroundLocationDisposeCallBack,
androidSettings: AndroidSettings(
accuracy: LocationAccuracy.NAVIGATION,
interval: 5,
distanceFilter: 0,
client: LocationClient.google,
androidNotificationSettings: AndroidNotificationSettings(
notificationChannelName: 'Location tracking',
notificationTitle: 'Start Location Tracking',
notificationMsg: 'Track location in background',
notificationBigMsg:
'Background location is on to keep the app up-tp-date with your location. This is required for main features to work properly when the app is not running.',
notificationIconColor: Colors.grey,
)));
}
I get an error on if (isDriverAvailable)
The error
Instance members can't be accessed from a static method.
Try removing the reference to the instance member, or removing the keyword 'static' from the method.
I can't remove the static keyboard on backgroundLocationCallBack(LocationDto location) as it is only meant to work with static method.
How else can I implement the bool check ?
You will need to somehow pass the isDriverAvailable boolean to your function, remove the static from the method, or refactor the whole thing.
Static members of a class need to be available from a class-level (in comparison to usual members being available on instance-level), which means that you don't get the implicit this member, as it is assumed you will call the function from the outside the instance.
I gave a quick glance to the background_locator package and its documentation, but nothing states this callback needs to be static, as long as it takes a LocationDto argument and returns void.

My useQuery hook is refetching everytime its called. I thought it is suppose to hand back the cache?

I'm a little confused here. I thought react-query, when using useQuery will hand back 'cache' n subsequent calls to the same "useQuery". But everytime I call it it, it refetches and makes the network call.
Is this the "proper way" to do this? I figured it would just auto hand me the "cache" versions. I tried extending staleTime and cacheTime, neither worked. Always made a network call. I also tried initialData with the cache there.. didn't work.
SO, I am doing the following, but seems dirty.
Here is the what I have for the hook:
export default function useProducts ({
queryKey="someDefaultKey", id
}){
const queryClient = useQueryClient();
return useQuery(
[queryKey, id],
async () => {
const cachedData = await queryClient.getQueryData([queryKey, id]);
if (cachedData) return cachedData;
return await products.getOne({ id })
}, {
enabled: !!id
}
);
}
This is initiated like so:
const { refetch, data } = useProducts(
{
id
}
}
);
I call "refetch" with an onclick in two diff locations.. I'd assume after I retrieve the data.. then subsequent clicks will hand back cache?
I’m afraid there are multiple misconceptions here:
react query operates on stale-while-revalidate, so it will give you data from the cache and then refetch in the background. You can customize this behavior by setting staleTime, which will tell the library how long the data can be considered fresh. No background updates will happen.
when you call refetch, it will refetch. It’s an imperative action. If you don’t want it, don’t call refetch.
you don’t need to manually read from the cache in the queryFn - the library will do that for you.

How to determine whether user is ready and nonce can be submitted to server?

This is one of many (imho rather incomplete) examples in the docs:
var button = document.querySelector('#submit-button');
braintree.dropin.create({
authorization: 'CLIENT_AUTHORIZATION',
container: '#dropin-container'
}, function (createErr, instance) {
button.addEventListener('click', function () {
instance.requestPaymentMethod(function (requestPaymentMethodErr, payload) {
// Submit payload.nonce to your server
});
});
});
It's all nice and easy but I don't see how I can change the state of button according to the state of "is the user done with adding a payment method?".
Is this even possible? It seems that the click on the button actually performs the fetching of the nonce (which comes as payload.nonce). However, how can I disable button until the user has finished his conversation with Braintree/PayPal?
And the answer is look in the docs (no not those docs) - those docs.
I still don't know how I found that link.
The dropin instance has a on() function where you can register a callback for certain events (just do it - look at the docs already):
instance.on('paymentMethodRequestable', function(event) {
thiz._logger.info('Payment method is now requestable');
setTimeout(() => thiz.paymentMethodAvailable = true, 400);
});

Google Dart: change event for IListElement

I'm wondering if you can listen for when the elements of a UListElement has changed (i.e. LIElement added or removed)?
UListElement toDoList = query('#to-do-list');
LIElement newToDo = new LIElement();
newToDo.text = "New Task";
toDoList.elements.add(newToDo);
// how do I execute some code once the newToDo has been added to the toDoList?
I'm assuming elements.add() is asynchronous as I come from an ActionScript background. Is this a valid assumption?
Higher level frameworks give you events for this, but at the HTML5 API level, you have to use a MutationObserver.
Here's an example where a mutation observer can be set on any DOM Element object. The handler can then process the mutation events as needed.
void setMutationObserver(Element element){
new MutationObserver(mutationHandler)
.observe(element, subtree: true, childList: true, attributes: false);
}
void mutationHandler(List<MutationRecord> mutations,
MutationObserver observer){
for (final MutationRecord r in mutations){
r.addedNodes.forEach((node){
// do stuff here
});
r.removedNodes.forEach((node){
// or here
});
}
}
element.elements.add(otherElement) is synchronous and is the equivalent of element.appendChild(otherElement) in Javascript (ie. DOM Level 2 Core : appendChild).
You may also be interested in our work with MDV:
http://blog.sethladd.com/2012/11/your-first-input-field-binding-with-web.html
http://blog.sethladd.com/2012/11/your-first-model-driven-view-with-dart.html