Skip to content

Commit 728dd29

Browse files
committed
update formatting + add message flow img
1 parent 5e5b889 commit 728dd29

File tree

2 files changed

+22
-34
lines changed

2 files changed

+22
-34
lines changed
89.6 KB
Loading

docs/ff-concepts/existing-flutter/method-channels.md

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -80,28 +80,14 @@ This message flow is asynchronous and decoupled:
8080
* **Method Handler**: Native code uses a handler (e.g., `setMethodCallHandler` on Android) to listen for calls and run logic when the specified method name is matched.
8181
* **Result Callback**: The native handler must return a result via `result.success(...)`, `result.error(...)`, or `result.notImplemented()`. These responses are passed back to Dart, completing the `Future`.
8282
83-
### Example Message Flow {#example-message-flow}
83+
### Example Message Flow
8484
85-
```
86-
Flutter (Dart)
87-
|
88-
| invokeMethod('getBatteryLevel')
89-
v
90-
Native (Kotlin/Swift)
91-
- Listens on 'com.example/battery'
92-
- Matches method name 'getBatteryLevel'
93-
- Executes logic to read battery level
94-
- Sends result back: success(85) or error(...)
95-
^
96-
| Future in Dart completes with 85 or throws PlatformException
97-
|
98-
Flutter (Dart)
99-
```
85+
![method-channels.png](imgs/method-channels.png)
10086
10187
This design ensures clear separation between platform and UI logic, and it keeps the UI thread non-blocking for both Dart and native sides. It also makes the communication extensible—you can define as many methods as you need over a single channel or use multiple channels for modular organization.
10288
10389
104-
### When to Use a MethodChannel {#when-to-use-a-methodchannel}
90+
### When to Use a MethodChannel
10591
10692
MethodChannel is most appropriate when:
10793
@@ -110,21 +96,21 @@ MethodChannel is most appropriate when:
11096
* You need to launch a platform-native UI (e.g., a full-screen scanner or a native file picker).
11197
* You’re bridging a legacy native feature into a Flutter app or gradually migrating a native app to Flutter.
11298
113-
### What MethodChannels Are Not {#what-methodchannels-are-not}
99+
### What MethodChannels Are Not
114100
115101
* They are not **shared memory** \- All data is copied through serialization, not shared by reference. Only standard types are supported (primitives, lists, maps, typed data). Large data transfers require full serialization/deserialization.
116102
* They are **not synchronous** \- Calls return Futures immediately without blocking. Results arrive asynchronously via the event loop. Platform errors surface as PlatformExceptions when the Future completes.
117103
* They are **not opinionated** \- You define the API contract (method names, arguments, types) on both sides. There's no compile-time validation across the boundary \- mismatches fail at runtime. Document your contract and validate inputs since type safety isn't enforced.
118104
119105
By understanding these characteristics, you can create robust, maintainable bridges between Dart and native code. You can write minimal, purpose-driven native handlers and keep the rest of your app in Flutter, achieving both deep platform access and cross-platform speed.
120106
121-
## Real-World Use Cases for MethodChannels {#real-world-use-cases-for-methodchannels}
107+
## Real-World Use Cases for MethodChannels
122108
123109
While Flutter plugins cover many common platform integrations, there are frequent scenarios where you require direct access to native SDKs or platform-specific APIs. MethodChannels offer a direct path for these integrations without waiting for third-party plugin support.
124110
125111
Ultimately, method channel integration is essentially plugin development \- you're writing the same native bridge packaged for your app instead of as a public package. Once complete, it can be imported into FlutterFlow. The following examples show when building your own native integration is more practical than waiting for or wrestling with existing plugins. The following examples outline situations where MethodChannels are suitable.
126112
127-
1. **Accessing Device Hardware Not Exposed by Plugins**
113+
### Accessing Device Hardware Not Exposed by Plugins
128114
129115
**Example:** Retrieve mobile network signal strength, advanced battery metrics, or thermal status.
130116
@@ -134,7 +120,7 @@ Ultimately, method channel integration is essentially plugin development \- you'
134120
135121
**Benefit:** Access hardware-level telemetry or diagnostics crucial for field-service apps, testing tools, or enterprise reporting.
136122
137-
2. **Integrating Proprietary SDKs or Vendor Libraries**
123+
### Integrating Proprietary SDKs or Vendor Libraries
138124
139125
**Example:** Use a third-party identity verification SDK, document scanner, or encrypted storage SDK.
140126
@@ -144,7 +130,7 @@ Ultimately, method channel integration is essentially plugin development \- you'
144130
145131
**Benefit:** Unlocks core business features (KYC, biometrics, payments) without dependency on plugin authors or external wrappers.
146132
147-
3. **Embedding Native UI Views Temporarily**
133+
### Embedding Native UI Views Temporarily
148134
149135
**Example:** Show a native PDF viewer, a camera UI from a vendor SDK, or an AR interface.
150136
@@ -153,7 +139,7 @@ Ultimately, method channel integration is essentially plugin development \- you'
153139
154140
**Benefit:** Delivers platform-native experiences where needed while preserving Flutter’s rendering pipeline elsewhere.
155141
156-
4. **Background Tasks and Event-Driven Native APIs**
142+
### Background Tasks and Event-Driven Native APIs
157143
158144
**Example:** Respond to geofencing events, push token refresh, or Bluetooth device state changes.
159145
@@ -163,7 +149,7 @@ Ultimately, method channel integration is essentially plugin development \- you'
163149
164150
**Benefit:** Achieves OS-level integration (e.g., location, power, Bluetooth) without polling or Dart-side complexity.
165151
166-
5. **Secure Device Data Retrieval**
152+
### Secure Device Data Retrieval
167153
168154
**Example:** Fetch IMEI, MAC address, device fingerprint, or system identifiers.
169155
@@ -267,22 +253,24 @@ class MainActivity: FlutterActivity() {
267253
268254
**Notes:**
269255
270-
* Always return a result using one of the following:
256+
- Always return a result using one of the following:
271257
* `result.success(data)` — returns data to Dart
272258
* `result.error(code, message, details)` — throws `PlatformException` in Dart
273259
* `result.notImplemented()` — throws `MissingPluginException` in Dart
274-
* Do **not** call `result` multiple times. Flutter expects a one-time, one-result reply per method call.
275-
* If your native call involves I/O, network, or anything that blocks, use a background thread:
276-
260+
- Do **not** call `result` multiple times. Flutter expects a one-time, one-result reply per method call.
261+
- If your native call involves I/O, network, or anything that blocks, use a background thread:
277262
```js
278-
Thread(Runnable {
279-
val resultData = longRunningOperation()
280-
runOnUiThread {
281-
result.success(resultData)
282-
}
283-
}).start()
263+
Thread(Runnable {
264+
val resultData = longRunningOperation()
265+
runOnUiThread {
266+
result.success(resultData)
267+
}
268+
}).start()
284269
```
285270
271+
272+
273+
286274
---
287275
288276
### 3. iOS Side (Swift)

0 commit comments

Comments
 (0)