import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'test flutter message channel', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const ContactPage(), ); } } class ContactDetails { ContactDetails({ required this.name, required this.phone, }); final String name; final String phone; factory ContactDetails.fromMap(Map map) => ContactDetails( name: map['name'] as String, phone: map['phone'] as String, ); Map toJson() => { 'name': name, 'phone': phone, }; } class ContactListModel { ContactListModel({ required this.contactList, }); final List contactList; factory ContactListModel.fromJson(String jsonString) { final jsonData = json.decode(jsonString) as Map; return ContactListModel( contactList: List.from((jsonData['contacts'] as List).map( (dynamic contactDetailsMap) => ContactDetails.fromMap( contactDetailsMap as Map, ), )), ); } String toJson() { String json = jsonEncode(contactList.map((i) => i.toJson()).toList()).toString(); return json; } } class ContactsMessageChannel { static const MethodChannel _methodChannel = MethodChannel('methodChannelDemo'); static const _jsonMessageCodecChannel = BasicMessageChannel('jsonMessageCodecDemo', JSONMessageCodec()); static void addContactDetails(ContactDetails contactDetails) { _jsonMessageCodecChannel.send(contactDetails.toJson()); } static Future getContacts(String type) async { final reply = await _jsonMessageCodecChannel.send('getContact$type'); if (reply == null) { throw PlatformException( code: 'INVALID', message: 'Failed to get contact', details: null, ); } else { return ContactListModel.fromJson(reply); } } static Future setContacts(json, String type) async { final result = await _methodChannel .invokeMethod('setContacts$type', {'contacts': json}); return result!; } } class ContactPage extends StatefulWidget { const ContactPage({super.key}); @override State createState() => _ContactPageState(); } class _ContactPageState extends State { static const int invokeCount = 1000; ContactListModel contactListModel = ContactListModel(contactList: []); String dataType = '1000'; String dataTypeText = '1'; int getCount = 0; int getSetCount = 0; final List timeList = []; _setDataType() async { setState(() { if (dataType == '1000') { dataType = '100'; dataTypeText = '0.1'; } else { dataType = '1000'; dataTypeText = '1'; } //dataTypeText = (dataType / 1000).toString(); }); } Future _getContactData() async { // 记录开始时间 var startDateTime = DateTime.now(); // 循环调用 1000 次 for (int i = 0; i < invokeCount; i++) { contactListModel = await ContactsMessageChannel.getContacts(dataType); } // 记录结束时间 var endDateTime = DateTime.now(); // 计算消耗的毫秒数 var totalMilliseconds = endDateTime .difference(startDateTime) .inMilliseconds; getCount++; timeList.add("第 $getCount 次读取总耗时=$totalMilliseconds 毫秒"); // 更新界面 setState(() {}); } Future _getSetContactData() async { // 记录开始时间 var startDateTime = DateTime.now(); // 先从Java层读取 1KB 联系人,然后序列为JSON后在Java层还原 for (int i = 0; i < invokeCount; i++) { contactListModel = await ContactsMessageChannel.getContacts(dataType); await ContactsMessageChannel.setContacts(contactListModel.toJson(), dataType); } // 记录结束时间 var endDateTime = DateTime.now(); // 计算消耗的毫秒数 var totalMilliseconds = endDateTime .difference(startDateTime) .inMilliseconds; getSetCount++; timeList.add("第 $getSetCount 次读取+写入总耗时=$totalMilliseconds 毫秒"); setState(() {}); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme .of(context) .colorScheme .inversePrimary, title: const Text('test flutter message channel'), ), body: Flex( direction: Axis.horizontal, crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Flexible( flex: 1, child: BuildTimeListWidget(timeList), ), Flexible( flex: 1, child: contactListModel.contactList.isEmpty ? const Center(child: Text('no data')) : BuildContactListWidget(contactListModel.contactList), ), Flexible( flex: 1, child: ListView( children: [ Container(height: 10), GestureDetector( behavior: HitTestBehavior.opaque, child: Text('数据长度约 $dataTypeText KB'), onTap: () { _setDataType(); }, ), Container(height: 10), const Text('循环执行 1000 次'), Container(height: 15), ElevatedButton(onPressed: _getContactData, child: const Text('读取原生对象数据'), ), ElevatedButton(onPressed: _getSetContactData, child: const Text('读取并写回原生对象'), ), ], ), ), ], ), // This trailing comma makes auto-formatting nicer for build methods. ); } } class BuildContactListWidget extends StatelessWidget { final List contactList; const BuildContactListWidget(this.contactList, {super.key}); @override Widget build(BuildContext context) { return ListView.builder( padding: const EdgeInsets.all(1), itemCount: contactList.length, itemBuilder: (context, index) { return ListTile( title: Text(contactList[index].name, style: const TextStyle(fontSize: 12),), subtitle: Text(contactList[index].phone, style: const TextStyle(fontSize: 12),), ); }, ); } } class BuildTimeListWidget extends StatelessWidget { final List timeList; const BuildTimeListWidget(this.timeList, {super.key}); @override Widget build(BuildContext context) { return ListView.builder( padding: const EdgeInsets.all(2), itemCount: timeList.length, itemBuilder: (context, index) { return ListTile( title: Text(style: const TextStyle(fontSize: 12), timeList[index]) ); }, ); } }