i have better understanding in how the delegates and events work , but i dont know
where it is of full use when we develop a Library or a application.
thanks
Delegates are significant as they are needed to work with events (not just this).
Lets say we have a winform F1..A function within F1 opens another form F2. and if a function within F1 has to be executed based on users activity on F2 we'll definitely have to make use of delegates and events.
1)A delegate type has to be declared (Signature has to match with eventhandler which you are planning to attach)
2)F2 will need to have an event as class member of delegate type
3)Just as you create an instance of F2 in F1 , attach the event handler (using += )
Delegates are similar to function pointers of C/C++ but are of class type and not primitive type.
The basic use of delegates is to perform some call back or asynchronous methods or to pass different methods at runtime. (substituting the logic)
Example for performing asynchronous call back. It is more appropriate when you have multiple threads running.
public class MyClass
{
public delegate void CallBackDelegate(int result);
public void CallsBack(CallBackDelegate callBack)
{
// your code here - do something useful
callBack(result);
}
}
public class DelegateExample
{
// some more useful code here
void ExampleMethod()
{
// more code
MyClass myclass = new MyClass();
myclass.CallsBack(CallMeBack);
// Continue with your work and don't wait for call back.
}
void CallMeBack(int result)
{
// do something useful
}
}
This is a very general question, but a typical use of delegates and events would be in a GUI library. For example, you could set up events to fire when a button is clicked on an application, or when a value is changed in a field, and a developer could then use delegates to specify one of their own functions to be called in response to that button click, or to perform validation on the changed data.
Related
I'm using SingleLiveEvent to communicate my ViewModel and my Activity. Something like that (pseudocode):
class MyActivity: BaseActivity{
fun onCreate(){
//Init viewmodel and so on
viewModel.commands.observe(this, { command ->
logger.debug("Command received","------>>>>>>>"+command.javaClass.simpleName)
processCommand(command)
})
}
}
And my ViewModel is something like:
class MyViewModel(application: Application) : BaseAndroidViewModel(application) {
val command: SingleLiveEvent<CustomCommands> = SingleLiveEvent()
init{
loadOneThing()
command.postValue(CustomCommands.MessageCommand("one thing loaded"))
loadAnotherThing()
command.postValue(CustomCommands.MessageCommand("another thing loaded"))
}
}
The problem that I'm having, is that the Activity is receiving only the last command, and that is per design. SingleLiveEvent is a Child class from LiveData, and the documentation says the following for the method postValue:
* If you called this method multiple times before a main thread executed a posted task, only
* the last value would be dispatched.
Interestingly, if I set a breakpoint on the line that posts the commands, the emulator/device/main thread has time enough to process the first command, and the second command is sent too. But when executing the app without breakpoints, if the tasks that the viewmodel does between commands are done very fast (no rest requests or things like that, but some calculations), the main thread does not have time enough to finish the first command, and the second command is ignored.
But I really need the View to receive all events/commands that the ViewModel sends.
I suppose the SingleLiveEvent is not the right tool for that use case, nor is LiveData, because of the problem of already consumed events being resent when the device is rotated and so on.
Somebody knows a better approach to do this?
Thanks in advance!
I have faced same problem today. I'm also using SingleLiveEvent for commands/event. I have solved this problem using
commands.value = event instead of commands.postValue(event). Then I wonder why it behaving like that. I found this article. In the article,
But for postValue, the value will be updated twice and the number of times the observers will receive the notification depends on the execution of the main thread. For example, if the postValue is called 4 times before the execution of the main thread, then the observer will receive the notification only once and that too with the latest updated data because the notification to be sent is scheduled to be executed on the main thread. So, if you are calling the postValue method a number of times before the execution of the main thread, then the value that is passed lastly i.e. the latest value will be dispatched to the main thread and rest of the values will be discarded.
I hope it help someone that faced same problem.
have you tried using EventObserver?
/**
* Used as a wrapper for data that is exposed via a LiveData that represents an event.
*/
open class Event<out T>(private val content: T) {
#Suppress("MemberVisibilityCanBePrivate")
var hasBeenHandled = false
private set // Allow external read but not write
/**
* Returns the content and prevents its use again.
*/
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled) {
null
} else {
hasBeenHandled = true
content
}
}
/**
* Returns the content, even if it's already been handled.
*/
fun peekContent(): T = content
}
/**
* An [Observer] for [Event]s, simplifying the pattern of checking if the [Event]'s content has
* already been handled.
*
* [onEventUnhandledContent] is *only* called if the [Event]'s contents has not been handled.
*/
class EventObserver<T>(private val onEventUnhandledContent: (T) -> Unit) : Observer<Event<T>> {
override fun onChanged(event: Event<T>?) {
event?.getContentIfNotHandled()?.let {
onEventUnhandledContent(it)
}
}
}
Use it with live data
val someEvent: MutableLiveData<Event<Unit>>= MutableLiveData()
when you need to some event
fun someEventOccured(){
someEvent.value = Event(Unit)
}
Fragment file, observe the Event
viewModel.someEvent.observe(this, EventObserver {
//somecode
})
Is it possible to typecast an object like so (let the code speak for itself):
protocol Parent {
...
}
class Child<LiterallyAnyValue, SameAsThePrevious>: Parent {
...
}
And then when using it:
func foobar(parent: Parent) {
if parent is Child { //ONE
print(parent as! Child) //TWO
}
}
At the signed points xcode wants me to supply the two types of "Child" within <> like Child<Int, String>...
The problem is that those types could be anything... LITERALLY
(And I've tried Child<Any, Any> but that doesn't work in this case)
Is there a workaround or a solution to this?
-------- Clarification --------
I am working on an iOS 7 project so I can't really use any modern library :)
That is including PromiseKit and Alamofire and the app has to make tons of http requests. The use promises in requests has grown on me, so I created my own Promise class.
At first I made it so that the Promise class would not be a generic and it would accept Any? as the value of the resolution procedure.
After that I wanted to improve my little Promise class with type clarification so the class Promise became "class Promise<T>"
In my implementation the then method created a PromiseSubscriber which then would be stored in a Promise property called subscribers.
The PromiseSubscriber is the protocol here that has two subset classes, one being PromiseHandler (this is called when the promise is resolved), and the other the PromiseCatcher (this is called when the promise is rejected)
Both PromiseSubscriber subset classes have a property called promise and one called handler.
These classes are also generics so that you know what kind of Promise they store and what is the return type of the handler.
In my resolution process I have to check if the PromiseSubscriber is a (let's say) PromiseHandler and if it is then call the handler that returns something and then resolve the subscribed promise with that value.
And here is the problem. I can't check if the subscriber is a catcher or a handler...
I hope it's clear enough now. Maybe this is not the right approach, I honestly don't know I am just trying to create something that is fun and easy to use (code completion without checking the type).
If it's still not clear and you are willing to help me, I'll send over the classes!
It's a little difficult to understand what you're really trying to do here (please tell me it's something other than JSON parsing; I'm so tired of JSON parsing and it's the only thing people ever ask about), but the short answer is almost certainly no. Some part of that is probably a misuse of types, and some part of that is a current limitation in Swift.
To focus on the limitation in Swift part, Swift lacks higher-kinded types. It is not possible to talk about Array. This is not a type in Swift. You can only work with Array<Int> or Array<String> or even Array<T>, but only in cases where T can be determined at compile time. There are several ways to work through this, but it really depends on what your underlying problem is.
To the misuse of types side, you generally should not have if x is ... in Swift. In the vast majority of cases this should be solved with a protocol. Whatever you were going to do in the if, make it part of the Parent protocol and give it a default empty implementation. Then override that implementation in Child. For example:
protocol Parent {
func doSpecialThing()
}
extension Parent {
func doSpecialThing() {} // nothing by default
}
class Child<LiterallyAnyValue, SameAsThePrevious>: Parent {}
extension Child {
func doSpecialThing() {
print(self)
}
}
func foobar(parent: Parent) {
parent.doSpecialThing()
}
Thanks for the clarification; Promise is a great thing to play with. Your mistake is here:
In my resolution process I have to check if the PromiseSubscriber is a (let's say) PromiseHandler and if it is then call the handler that returns something and then resolve the subscribed promise with that value.
Your resolution process should not need to know if it's a handler or a catcher. If it does, then your PromiseSubscriber protocol is incorrectly defined. The piece it sounds like you're missing is a Result. Most Promise types are built on top of Result, which is an enum bundling either success or failure. In your scheme, handlers would process successful Results and ignore failing results. Catchers would process failing results and ignore successful Results. The promise resolution shouldn't care, though. It should just send the Result to all subscribers and let them do what they do.
You can build this without a Result type by using a protocol as described above.
protocol PromiseSubscriber {
associatedType Wrapped // <=== It's possible you've also missed this piece
func handleSuccess(value: Wrapped)
func handleFailure(failure: Error)
}
extension PromiseSubscriber {
func handleSuccess(value: Wrapped) {} // By default do nothing
func handleFailure(failure: Error) {}
}
class PromiseHandler<Wrapped> {
func handleSuccess(value: Wrapped) { ... do your thing ... }
}
class PromiseCatcher {
func handleFailure(failure: Error) { ... do your thing ... }
}
I recommend studying PinkyPromise. It's a nice, simple Promise library (unlike PromiseKit which adds a lot of stuff that can make it harder to understand). I probably wouldn't use a protocol here; the associatedtype makes things a bit harder and I don't think you get much out of it. I'd use Result.
Use a generic type in your foobar function, the one below requires the parent parameter to conform to the Parent protocol and T will represent the class of the object passed.
func foobar<T: Parent>(parent: T) {
print(parent)
}
Universal App with MVVMLight.
So I started wondering why all the SDK examples were done from code behind rather than using a solid Wrapper class.
So I wanted to write a reusable wrapper class. No luck. Even tried adding that wrapper to a ViewModel, still no luck.
Works fine from MainView.xaml.cs
IBandInfo[] pairedBands = BandClientManager.Instance.GetBandsAsync().Result;
if (pairedBands.Length > 0)
{
using (IBandClient bandClient = await BandClientManager.Instance.ConnectAsync(pairedBands[0]))
{
}
}
The moment I move to any kind of OOP or View Model, ConnectAsync will never return or throw exception. I have tried this 20 different ways, is the SDK broken? What Is happening? No message, no throw, just never returns.
If I throw in Code behind, wallah it works just fine and returns the client in 1/2 second.
I have spend 5-6 hours so far on this. I wanted to create a solid wrapper class for the SDK so I could call easy calls from Model and do things like StartListener(MicrosoftBandSensor sensorToActivate).
Any suggestions?
-- For Phil's comment
I was trying to create backing variables for both client and bandinfo which would be held in a class that the VM uses. I wrote my class as IDisposable so I could dispose of both when I was done with my wrapper. I may be using this wrong to be honest.
MicrosoftBand.MicrosoftBandClient = BandClientManager.Instance.ConnectAsync(pairedBands[0]).Result;
Is what I wanted to call making it a sync call since I wanted to make the calls to bandinfo and client in the constructor then hold both until the class was destroyed and just recall the vars when needed.
My VM has :
public BandInformation MicrosoftBand
{
get { return _microsoftBand; }
set { Set(() => MicrosoftBand, ref _microsoftBand, value); }
}
If they didn't pass the bandclient in the constructor I would use:
private async Task InitBand(IBandInfo bandInfo)
{
if (bandInfo == null)
{
var allBands = await BandClientManager.Instance.GetBandsAsync();
if (allBands.Length > 0)
{
bandInfo = allBands[0];
}
}
var bandClient = await BandClientManager.Instance.ConnectAsync(bandInfo);
MicrosoftBandInfo = bandInfo;
MicrosoftBandClient = bandClient;
if (MicrosoftBandClient == null)
{
AddErrorMessage("This sample app requires a Microsoft Band paired to your device.Also make sure that you have the latest firmware installed on your Band, as provided by the latest Microsoft Health app.");
}
}
This seems fine working with BandInfo. I get back a solid seeming to work object For the client I get "thread exited" and nothing else.
Note: I had it in a try catch throwaway version at one point and nothing threw n exception either.
I assume you can do this like you would any other IDisposable where you handle the disposing yourself.
I can reinstantiate the BandClient each time, just figured I needed to detach the events at some point, meaning I had to keep ahold of the bandclient. I could keep it until done and would add and remove events as I needed each time.
It's likely your blocking call to .Result within your VM constructor is what was causing the hang. IBandClientManager.ConnectAsync() may implicitly display UI (a Windows Runtime dialog asking the user to confirm that she wants to use that specific Bluetooth device). If you've blocked the UI thread when it attempts to display UI, you've now gotten yourself into a deadlock.
Calling Task.Result is almost never a good idea, much less doing so within a constructor where you have little idea on which thread the constructor is executing. If you're working with an async API (such as the Band SDK) then your best bet is to keep that interaction async as well. Instead, defer calling ConnectAsync() until you actually need to, and do so from an async method in your VM. (Deferring the connection is a good idea anyway because you want to minimize the time connected to the Band to preserve battery life.) Then call Dispose() as early as possible to close the Bluetooth connection.
So I went and looked at a bunch of examples. Finally I landed on the GravityHeroUAP demo on the MSDN site. https://msdn.microsoft.com/en-us/magazine/mt573717.aspx?f=255&MSPPError=-2147217396
I looked at his code and the source: https://github.com/kevinash/GravityHeroUWP
He was essentially doing what I wanted to do.
However, I noticed something Bizarre. In his viewmodel everything was static!
public static IBandInfo SelectedBand
{
get { return BandModel._selectedBand; }
set { BandModel._selectedBand = value; }
}
private static IBandClient _bandClient;
public static IBandClient BandClient
{
get { return _bandClient; }
set
{
_bandClient = value;
}
}
I ended up copying this pattern (though had to throw away my favorite MVVM lib in the process, though I am sure I can get it back).
My common pattern in my VM's:
public string ExceptionOnStart {
get { return _exceptionOnStart; }
set { Set(() => ExceptionOnStart, ref _exceptionOnStart, value); }
}
It seems to be working now!
That and I got data way too fast for the
await Windows.Storage.FileIO.AppendLinesAsync(dataFile, new List<string> { toWrite });
Thank you for the help Phil, it got me looking in the right direction!
Thank you very, very much. Spent WAY to long on this. Mark
AS some one porting code from actionscript to IOS, We have a lot of custom components that follow the event dispatching mechanism in Flash/Actionscript:
E.g. dispatcher:
dispatchEvent(new CustomEvent(CustomEvent.DRAG_DROP));
Consumer:
dispatcher.addEventListener(CustomEvent.DRAG_DROP, actionHandler);
private function actionHandler(event:CustomEvent):void {
trace("actionHandler: " + event);
}
I know of NSNotificationCenter, KVO pattern, action-target, but none seem to be an exact match?
Where would I define CustomEvent? CustomEvent.DRAG_DROP? and how would the consumer listen for the event? How would a consumer know of all the events that a dispatcher can dispatch? I do not wish to use a delegate because there could be multiple consumers.
The closes way I know is selectors ...
// store event handler
SEL targetHandler;
// firing an event
[targetHandler performSelector:targetHandler withObject:eventObj];
// event handler in the listening class
- (void) onStuffHappened: (Event*) event
{
}
that's obviously a quick thought, I would extend NSObject and store handlers in NSMutableArray then run performSelector on all the stored handlers ... something like that
or you can use delegates for a cleaner way.
Generally this is done with a list of delegates. If you want a multiple consumers, define a protocol (just like you would for a delegate), and then create an array of those objects. When you want to communicate with all of the listeners iterate through the list of listeners sending the event to each one.
I'm experimenting some WebGL in Dart and I had created a class that loads shaders from separate files and I would like to throw an event (function) when the object is ready, so I can continue my application knowing that my shaders are properly loaded. Do someone knows an easy way to do this?
One approach is to use a Future pattern to accomplish this:
Future<SomeType> initMyObject(){
final c = new Completer();
// Do my object init stuff
// and when it is complete:
c.complete(instanceOfSomeType);
// Return the Future object to any subscribers.
return c.future;
}
Then elsewhere you can get notified like so:
initMyObject().then((SomeType t){
//executes when future completes
});