1. What is drive
Baidu Encyclopedia tells us that drive is to promote, event driven is to use one event after another, to promote the execution of an operation.
2. Loop
In our series of Java programming programs, Android is a typical event-driven application. Those familiar with Android development must know that the underlying Looper is constantly looping, and messages are processed when encountered, otherwise blocked at messagequeue.next (). One method we use very often: runOnUiThread is used to perform an operation on the main thread, because Android doesn’t allow us to manipulate the UI on child threads. But have you thought about how he did it?
It’s really simple:
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
Copy the code
Check whether the current thread is the main thread. If it is, it will execute directly. Otherwise, it will post to the main thread via Handler mechanism, which will be retrieved and executed by the child thread’s Looper.
For example, if we want the system to load data after requesting the network, and then update the view after the data is returned, the “data return” is actually an event. Since it is an event, we must consume it, so we call runOnUiThread and give it to the main thread to consume.
In fact, in any call stack of the main thread, the method at the bottom of the call stack must be loop method, because all operations on the main thread are to add a Message to the MessageQueue of the main thread, and then looper takes out the operation. Message can even come with a Runnable to execute code. You can also attach some information to be processed in the callback office.
3. An OnClickListener events
We usually call setOnClickListener in the View to set the click event. In addition to setting the View.OnClickListener and XML, The current Activity is usually used to implement the view. OnClickListener interface, rewrite the onClick method, according to the ID to determine the object generated by the click event, and then determine the specific click event.
For example, if we set up a button and click the button to request the network, then the click event will be the driver of the request network. This is a very simple event-driven process.
4. Event-driven model
The event-driven model has three elements: event source, listener, and event. Those familiar with design patterns should quickly recognize that these three elements are very similar to the three components of the Observer pattern. In fact, the event-driven model is customized based on the observer.
The steps of the event-driven model are as follows:
- define
The listener
Write a handler for each event. - will
The listener
Object registration toThe event source
The event source
When an event occurs, the corresponding method in the listener is called to complete the processing of the event.
The above 3 steps, in the OnClick event, correspond to:
Val Events = view.onClickListener {toast.maketext (this@MainActivity,"HelloWorld!") ,Toast.LENGTH_SHORT).show() } //2. Register with event source findViewById<TextView>(R.I.T.V).setonClickListener (events) //3. When we tap our finger on the screen and generate an event (that is, an event source generates an event), we distribute the event to the target, which is ultimately consumed by the touched View.Copy the code
5. The Dart and Flutter
The asynchronous programming of Flutter: Future, Isolate, and event loops. This article is written with his full reference.
Dart is a single-threaded model, whereas Flutter relies on Dart. The single-threaded model has a problem: one operation can be performed at a time, and other operations can only be performed after it.
We know that we can’t write an infinite loop in Android, which would cause ANR, but Flutter does the same thing. In Dart, if we write a large for loop, then performing operations in the loop would also cause the thread to block and the interface to block. For example, executing a loop in the overwritten setState(), You must wait until the end to load the screen.
But in today’s complex business logic requirements, our single-threaded model is actually difficult to meet a variety of requirements. So Dart uses a code sequencer (event loop).
When we start a DartApp, a new thread process will be built, known as the Isolate in Dart, and this thread will be the only one you need to focus on in the entire application.
So, after this thread is created, Dart will automatically:
- Initialize two FIFO queues (MicroTask and Event)
- And when the method completes, the Main method is executed
- Start the
Event loop
An event loop is an infinite loop, and within each clock cycle, if no other Dart code executes, then:
void eventLoop(){ while (microTaskQueue.isNotEmpty){ fetchFirstMicroTaskFromQueue(); executeThisMicroTask(); return; } if (eventQueue.isNotEmpty){ fetchFirstEventFromQueue(); executeThisEventRelatedCode(); }}Copy the code
We can see from the sequence that the MicoTask queue takes precedence over the Event queue.
5.1 MicroTask queue
MicroTask queues are used for very short internal actions that need to be executed asynchronously, after other events have completed and before execution is handed over to the Event queue.
5.2 the Event queue
The Event queue applies to the following reference models:
- IO
- gestures
- drawing
- The timer
- flow
- futures
In fact, every time an external Event is triggered, the code that needs to be executed is referenced by the Event queue. Once no MicroTask is running, the Event loop will consider the first item in the Event queue and execute it, and the Future operation will also be performed by the Event queue.
5.3 the Future
A Future is a task that executes asynchronously and either completes or fails at some point in the Future. When instantiating a Future:
- An instance of the Future is created and recorded in an internal array managed by Dart.
- The code that needs to be executed by this Future is pushed directly into the Event.
- The Future instance returns a state (=incomplete)
- If the next synchronization code exists, it is executed.
As long as the Event loop fetches it from the Event loop, the code referenced by the Future will execute like any other Event.
Then or cacheError callbacks are triggered when the code change is about to complete (or fail).
In the following example:
void main(){
print('Before the Future');
Future((){
print('Running the Future');
}).then((_){
print('Future is complete');
});
print('After the Future');
}
Copy the code
Order of output:
Before the Future
After the Future
Running the Future
Future is complete
Copy the code
Processes performed:
- Print (” Before “the” Future “)
- Will () {print (‘ Running the Future “); } add to the Event queue;
- Print (‘ After the Future ‘
- The event loop takes the code referenced in step 2 and executes it
- When the code executes, it looks for the THEN () statement and executes it
Therefore, Flutter/Dart uses an Event loop to simulate concurrent requests.
When the Aysnc method is in use, Dart thinks that the return value of the method is a Future, executes the method synchronizes until it encounters the first await keyword, then suspends the rest of the method, and once the Future referenced by the await keyword completes, the next line of code executes immediately.
Take this example:
void main() async { methodA(); await methodB(); await methodC('main'); methodD(); } methodA(){ print('A'); } methodB() async { print('B start'); await methodC('B'); print('B end'); } methodC(String from) async { print('C start from $from'); Future((){// <== print('C running Future from $from') at some point in the Future; }).then((_){ print('C end of Future from $from'); }); print('C end from $from'); } methodD(){ print('D'); }Copy the code
Start with the Main method and pause at the first await.
A
B start
C start from B
C running Future from B
C end of Future from B
C end from B
B end
C start from A
C running Future from A
C end of Future from A
C end from A
D
Copy the code
But here’s the thing:
The Future code in A B start C start from B C end from B -- C will be executed later, not immediately. B end C start from main C end from main D -- C Running Future from B C end of Future from B C Running Future from main C end of Future from mainCopy the code
This is a bit different from what we think of as multi-threaded (asynchronous) processing, where the threads each advance in an unknown order, but the single-threaded Dart emulates asynchronous operations by relying on an event loop, but we found that all futures are put to the end of the code. Predicting program execution becomes very difficult.
We also know that await blocks at the current code location, so we can use await with Future to get synchronous effect, i.e. the code will wait until the Future is finished executing:
methodC(String from) async {
print('C start from $from');
await Future((){ // <== change it here
print('C running Future from $from');
}).then((_){
print('C end of Future from $from');
});
print('C end from $from');
}
Copy the code
In this case, it is possible to execute down after C start and wait for C execution to complete.
So, asynchronous execution in Dart is actually just following the Event handling rules of the Event, not really asynchronous execution:
5.4 Isolate
Does Flutter/Dart have its own thread? Isolate.
The ISOLates do not share memory in Flutter. Different ISOLates communicate with each other through messages.
Each Isolate has its own Event loops and queues (microtasks and events), which means that the code running in one Isolate has no relationship with the other.
Doesn’t it look like Loop?
5.4.1 How Can I Enable itIsolate
?
We need to establish communication between the caller and the new Isolate.
Each Isolate exposes a port called SendPort for passing messages to the Isolate (this is a listening port, not for sending).
This means that the caller and the New Isolate need to know each other’s ports in order to communicate. See source 1 for details
We have a port can send messages, finally remember to dispose in the dispose.
This is a simplex communication mode (single listening stream), we can only hear the message sent by the other party, to achieve duplex communication needs to establish two listening streams between each other.
5.5 the conclusion
Flutter’s event loop mechanism is a bit like Android threads’ Looper, but Dart is single-threaded, while Future and Isolate can implement or simulate asynchronous operations and play a very important role in development.
Reference source
- Flutter asynchronous programming: Future, Isolate, and event loops