Плагин Flutter более безопасная/правильная настройка для отображения различных собственных экрановAndroid

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Плагин Flutter более безопасная/правильная настройка для отображения различных собственных экранов

Сообщение Anonymous »

Я работаю над плагином Flutter, который показывает несколько собственных экранов, но в качестве документации ни для https://docs.flutter.dev/platform-integ ... form-views, ни для https://docs.flutter. dev/platform-integration/android/platform-views предлагает особый подход для этого случая. Я не уверен, следует ли мне регистрировать в плагине несколько FlutterPlatformViewFactory и FlutterPlatformView, каждый из которых указывает на определенное собственное представление. или безопасно зарегистрировать только одну пару и динамически прикрепить нужное мне собственное представление экрана к FlutterPlatformView, передав значение в параметрах представления из Flutter и выбрав нужный мне экран с помощью перечисления, как я реализовал здесь :
перечисление встроенного переключателя экрана

Код: Выделить всё

import Foundation
import Flutter

enum ViewControllerGetter: String {
case viewController
case viewController2

func getViewController (with params: [String: AnyObject]?) -> UIViewController? {
switch self {
case .viewController:
if params != nil {
var vc : UIViewController = UIViewController()
// first we get the binaryMessenger from params as it has been added to them in FlutterPlatformView
if let binaryMessenger = params!["binaryMessenger"] as? FlutterBinaryMessenger {

print("ViewControllerGetter binaryMessenger \(binaryMessenger.description)");
// then we initialize the ViewController with it, to create a FLutterMethodChannel which needs a binaryMessenger
// than normally we take from AppDelegate rootViewController, but as theis is a Plug-in we don't have any AppDelegate
let vcToShow = ViewController(withParameter: binaryMessenger, methodChannelId: params!["methodChannelId"] as! String);

// then we set other ViwController variables and values
if let param1 = params!["param 1"] {
vcToShow.buttonTitleA = param1 as? String
}
if let param2 = params!["param 2"] {
vcToShow.buttonTitleB = param2 as? String
}
// then we overwrite the Empty ViewController to be returned with the instantiated ViewController
vc = vcToShow
}

// we can finally return the ViewController to be attached to the FlutterPlatformView UIView
return vc
}
case .viewController2:
if params != nil {
var vc : UIViewController = UIViewController()
// first we get the binaryMessenger from params as it has been added to them in FlutterPlatformView
if let binaryMessenger = params!["binaryMessenger"] as? FlutterBinaryMessenger {

print("ViewControllerGetter binaryMessenger \(binaryMessenger.description)");
// then we initialize the ViewController with it, to create a FlutterMethodChannel which needs a binaryMessenger
// than normally we take from AppDelegate rootViewController, but as this is a Plug-in we don't have any AppDelegate
let vcToShow = ViewController2(withParameter: binaryMessenger, methodChannelId: params!["methodChannelId"] as! String);

// then we set other ViewController variables and values
if let param1 = params!["param 1"] {
vcToShow.buttonTitleA = param1 as? String
}
if let param2 = params!["param 2"] {
vcToShow.buttonTitleB = param2 as? String
}

if let param3 = params!["param 3"] {
vcToShow.buttonTitleC = param3 as? String
}
// then we overwrite the Empty ViewController to be returned with the instantiated ViewController
vc = vcToShow
}

// we can finally return the ViewController to be attached to the FlutterPlatformView UIVIew
return vc
}

}
return nil
}
}
FlutterPlatformViewFactory — FlutterPlatformView

Код: Выделить всё

import Flutter
import UIKit

class DynamicNativeViewFactory: NSObject, FlutterPlatformViewFactory {
private var messenger: FlutterBinaryMessenger
init(messenger: FlutterBinaryMessenger) {
self.messenger = messenger
super.init()
}

func create(
withFrame frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?
) ->  FlutterPlatformView {
return DynamicNativeView(
frame: frame,
viewIdentifier: viewId,
arguments: args,
binaryMessenger: messenger)
}

public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
return FlutterStandardMessageCodec.sharedInstance()
}
}

class DynamicNativeView: NSObject, FlutterPlatformView {
private var vc: UIViewController = UIViewController();

init(
frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?,
binaryMessenger messenger: FlutterBinaryMessenger?
) {
if var params = args as? [String:AnyObject] {
print("DynamicNativeView binaryMessenger \(messenger?.description)");
let screen: String = params["screen"] as! String;
// we add the binary messenger
params["binaryMessenger"] = messenger;

if let vcToShow = ViewControllerGetter(rawValue: screen)?.getViewController(with: params) {

vc = vcToShow
// _view = vcToShow.view /// breaks touch
}
}
super.init()
// _view.addSubview(vc.view)
}

func view() -> UIView {
// _view.addSubview(vc.view)
// return _view
return vc.view
}
}
Плагин Flutter

Код: Выделить всё

import Flutter
import UIKit

public class NativePlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "native_plugin", binaryMessenger: registrar.messenger())

let instance = NativePlugin()
registrar.addMethodCallDelegate(instance, channel: channel)

let viewFactory = DynamicNativeViewFactory(messenger: registrar.messenger())
registrar.register(
viewFactory,
withId: "native_screen"
)
}

public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getPlatformVersion":
result("iOS " + UIDevice.current.systemVersion)
default:
result(FlutterMethodNotImplemented)
}
}
}

Виджет PlatformView плагина Flutter

Код: Выделить всё

class NativeViewer extends StatefulWidget {
final Map viewParams;
const NativeViewer({
super.key,
required this.viewParams,
});

@override
State createState() => _NativeViewerState();
}

class _NativeViewerState extends State {
@override
void initState() {
super.initState();
}

@override
Widget build(BuildContext context) {
const String viewType = 'native_screen';
final Map creationParams = widget.viewParams;

return AdatptivePlatformView(
viewType: viewType,
layoutDirection: TextDirection.ltr,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
);
}
}

class AdatptivePlatformView extends StatelessWidget {
final String viewType;
final dynamic creationParams;
final TextDirection? layoutDirection;
final MessageCodec? creationParamsCodec;
const AdatptivePlatformView({
super.key,
required this.viewType,
this.creationParams,
this.creationParamsCodec,
this.layoutDirection,
});

@override
Widget build(BuildContext context) {
return Platform.isAndroid
? AndroidView(
viewType: viewType,
layoutDirection: TextDirection.ltr,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
)
: UiKitView(
viewType: viewType,
layoutDirection: TextDirection.ltr,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
gestureRecognizers: {
Factory(
() =>  EagerGestureRecognizer(),
),
},
);
}
}
Оба подхода работают, но мне не удалось найти информацию о лучших и плохих практиках для этого случая.
Меня беспокоит следующее: что при регистрации только одного FlutterPlatformViewFactory с помощью плагина будет гарантировано отсутствие проблем с идентификатором, поскольку он только один, это может привести к таким проблемам, как утечки памяти, например, когда я использую виджет плагина на разных экранах Flutter, поэтому плагин зарегистрировал бы его снова с тем же идентификатором.
Я не нашел в документации никаких упоминаний о его отмене регистрации, поэтому я не знаю, является ли это безопасным подходом, поскольку, возможно, FlutterPlatformViewFactory получает отменяется регистрация при закрытии экрана Flutter, который использует виджет плагина, освобождая ресурсы, захваченные, как это происходит, когда новый FlutterMethodChannelHandler регистрируется на том же канале, отменяя регистрацию любого ранее зарегистрированного или он все равно остается зарегистрированным.Можете ли вы указать мне на какую-то часть документации, которую я пропустил, или на какую-либо статью или какой-нибудь плагин Flutter, который имеет несколько собственных экранов для своего пользовательского интерфейса?
Как всегда, ваша помощь очень ценится

Подробнее здесь: https://stackoverflow.com/questions/789 ... ve-screens
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Android»