Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to define the AIDL of Flutter

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >

Share

Shulou(Shulou.com)05/31 Report--

This article introduces the relevant knowledge of "how to define the AIDL of Flutter". Many people will encounter such a dilemma in the operation of actual cases, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Flutter's product definition is a high-performance cross-platform mobile UI framework that can build Android/iOS/Web/MacOS applications with one set of code. As a UI framework, it does not have some system interfaces, and naturally it can not avoid dealing with natives. As a result, it proposes something called platform channel, which is used for flutter and native flexible exchange of data. For the convenience of description, Android is used to refer to native.

Burning goose, it only supports the transmission of some basic data types and data structures, such as bool/int/long/byte/char/String/byte [] / List/Map, etc.

So, when you want to transfer complex data, you can only package it as Map, something like this:

Await _ channel.invokeMethod ('initUser', {' name': 'Oscar',' age': 16, 'gender':' MALE', 'country':' China'})

Then in the Android layer hard code, parse out different data corresponding to different key. If you are a pure fluter project and have no plans to deal with natives in the future, or just need to interact simply, then there is nothing wrong with this approach. When your project already has a large portion of native code or you need to use third-party lib libraries that don't support flutter, it means you need to write a lot of template code like the one above. It can be seen that the efficiency is low and the maintainability is poor. At this point, you will think, it would be nice to be able to transfer the object!

And when you want to transfer the object:

Sorry, no way. I can only give you an awkward and impolite smile. Of course, it's not impossible. We can serialize objects into json objects at the top of the native layer, and then convert json to flutter objects at the flutter layer, which is also inefficient.

What is FIDL?

Anyone who has studied Android should know AIDL (Android Interface Defination Language), which is the Android interface definition language. There is an advanced method of cross-process communication in Android-Binder, but if you want to use Binder, you need to understand some Binder mechanisms and API, and you need to write a lot of template code. In order to solve this problem, Android tried to make the method of using Binder a little bit white. So AIDL is defined, telling developers that your interface file must be written as I specify, and the objects you want to transfer across processes must implement the Parcelable interface. Then, Android generates a Service.Stub class for you, secretly serializing and deserializing objects behind your back. Using this Stub class, developers can easily get started with Binder, an advanced method of cross-process communication.

FIDL (Flutter Interface Defination Language), the Flutter interface definition language, has a mission similar to AIDL, quietly doing the "dirty work" of serialization, deserialization, and automatic code generation of objects. The classes that developers see in native code can automatically generate the same classes on the Dart side as in native code through the @ FIDL annotation tag. FIDL is a mirror that maps classes from various native platforms to Dart and classes from Dart to various native platforms.

Shut up and look at things first

The first is the Java class:

Public class User {String name; int age; String country; Gender gender;} enum Gender {MALE, FEMALE}

Android side

1. Define the FIDL interface

@ FIDL public interface IUserService {void initUser (User user);}

2. Execute the command. / gradlew assembleDebug to generate IUserServiceStub classes and fidl.json files

3. Open the channel and expose the method to Flutter

FidlChannel.openChannel (getFlutterEngine () .getDartExecutor (), new IUserServiceStub () {@ Override void initUser (User user) {System.out.println (user.name + "is" + user.age + "years old!");}}

Flutter side

1. Copy the fidl.json file to the fidl directory, execute the command flutter packages pub run fidl_model, and generate the Dart interface class.

2. Bind the IUserServiceStub channel on the Android side

Await Fidl.bindChannel (IUserService.CHANNEL_NAME, _ channelConnection)

3. Call the exposed method

Await IUserService.initUser (User ())

Compile, run, and you will see Oscar is 18 years old! in Logcat.

Detailed explanation of FIDL usage

This part is a supplementary explanation for the part that is less wordy and looks at things first, and the grandfathers of the audience can skip it on their own.

The Map in the above example, generally speaking, corresponds to a class in Java:

Public class User {String name; int age; String country; Gender gender;} enum Gender {MALE, FEMALE}

If you want flutter to transfer this object without having to write the User class manually at the flutter layer, as well as writing fromJson/toJson methods, you can do this:

Android side

1. Define an interface and add the annotation @ FIDL. This annotation will tell annotationProcessor to generate some description files for interfaces and classes.

@ FIDL public interface IUserService {void initUser (User user);}

The limitations of the interface method are as follows:

Since dart does not support method overloading, methods with the same name cannot appear in the interface

Parameters only support entity classes, not callbacks

Due to the limitation of JSON decoding, Java needs a nonparametric constructor.

2. Android Studio, click sync, or execute:

. / gradlew assembleDebug

A bunch of json files are then generated, as follows:

These json files are the description files for FIDL and classes. Yes, a description file for the Gender class referenced by User is also generated.

At the same time, an implementation IUserServiceStub for IUserService is generated. That is:

Com.infiniteloop.fidl_example.IUserService.fidl.json

Com.infiniteloop.fidl_example.User.json

Com.infiniteloop.fidl_example.Gender.json

Com.infiniteloop.fidl_example.IUserServiceStub.java

Limit: only FIDL files with strong reference relationships can be generated. If the subclasses of classes strongly referenced by FIDL API are not strongly referenced by FIDL API, the corresponding description file will not be generated.

3. Open the channel in the appropriate place and expose the method to Flutter

IUserServiceStub userService = new IUserServiceStub () {@ Override void initUser (User user) {System.out.println (user.name + "is" + user.age + "years old!");} FidlChannel.openChannel (getFlutterEngine () .getDartExecutor (), userService)

4. If necessary, you can close the channel in a suitable place

FidlChannel.closeChannel (userService)

The message of the shutdown is notified to the Flutter side.

Flutter side

1. Go to your flutter project, create a fidl directory under the lib directory, copy the above json file to this directory, and then execute:

Flutter packages pub run fidl_model

The relevant dart classes can then be automatically generated in the fidl directory:

That is:

User.dart

Gender.dart

IUserService.dart

2. Bind the IUserServiceStub channel on the Android side

Bool connected = await Fidl.bindChannel (IUserService.CHANNEL_NAME, _ channelConnection)

_ channelConnection is used to track the connection status of the IUserService channel. When the channel is connected successfully, its onConnected method is called back; when the channel connection is disconnected, its onDisconnected method is called back.

3. Call the public method of the channel

If (_ channelConnection.connected) {await IUserService.initUser (User ());}

If you no longer need to use this channel, you can unbind it.

Await Fidl.unbindChannel (IUserService.CHANNEL_NAME, _ channelConnection)

Of course, FIDL does more than that.

1. FIDL API for multiple parameters

Void init (String name, Integer age, Gender gender, Conversation conversation)

2. FIDL API with return value

UserInfo getUserInfo ()

3. Support the generation of generic classes

Public class User {T country;} public class AUser {}

FIDL interface:

Void initUser (AUser user)

AUser and User classes will be generated on the dart side, and inheritance relationships will be maintained.

4. Pass enumeration

Void initEnum0 (EmptyEnum e); String initEnum1 (MessageStatus status)

5. Transfer set, Map

Void initList0 (List ids); void initList1 (Collection ids); void initList7 (Stack ids); void initList10 (BlockingQueue ids)

6. Transfer complex objects. Inheritance, abstraction, generics, enumerations, and mixed classes, one at a time.

For now, the FIDL project only implements methods on the Android side that are called from the Dart side. The following work remains to be done:

The Android side calls the method of the Dart side

Mutual calls between other platforms and Flutter methods

EventChannel,EventChannel can essentially be implemented through MethodChannel, so it's not a problem.

Solved the object transmission, these problems, are small case.

For serialization and deserialization of objects

In order to meet the customization needs of the bosses, I defined serialization / deserialization interface classes on the Java side and the Fluter side, respectively.

Java: public interface ObjectCodec {List encode (Object... Objects); T decode (byte [] input, TypeLiteral type);} Dart: abstract class ObjectCodec {dynamic decode (Uint8List input); List encode (List objects);}

Currently using JsonObjectCodec, after JSON codec, the performance will be slightly worse. Later, I also hope to work with my friends to achieve more efficient codec.

Project schedule

Most of the functions mentioned above have been implemented as long as they are related to calling methods on the Java side from the Flutter side.

I made a Demo to simulate a scenario that relies on IM (instant messaging) SDK on the Android side and needs to chat, get messages, and send messages on the Flutter side. The following is a screenshot of Demo:

1. On the home page, click the button to call the Android side method to start the chat service.

2. Chat page

Send a message to Lucy and get the chat record with Lucy

4. Call the Android side method to send N messages to Wilson and get the chat record.

This is the end of the content of "how to define the AIDL of Flutter". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Database

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report