19.1 C
New York
Sunday, September 15, 2024

android – Flutter plugin safer/correct setup to indicate numerous native screens


I am engaged on a Flutter plugin that reveals a couple of native screens however because the documentation for https://docs.flutter.dev/platform-integration/ios/platform-views nor https://docs.flutter.dev/platform-integration/android/platform-views affords a particular strategy for this case I am unsure if I ought to register within the Plugin a number of FlutterPlatformViewFactory and FlutterPlatformView each level to a particular native view, or is it secure to register just one pair and dynamically connect the native display screen view i have to the FlutterPlatformView by passing a worth within the view params from Flutter and choosing the display screen I would like utilizing an enum and as I carried out right here:

import Basis
import Flutter

enum ViewControllerGetter: String {
    case viewController
    case viewController2

    func getViewController (with params: [String: AnyObject]?) -> UIViewController? {
        change self {
        case .viewController:
            if params != nil {
                var vc : UIViewController = UIViewController()
                // first we get the binaryMessenger from params because 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 wants a binaryMessenger
                    // than usually we take from AppDelegate rootViewController, however as theis is a Plug-in we haven't any AppDelegate
                    let vcToShow = ViewController(withParameter: binaryMessenger, methodChannelId: params!["methodChannelId"] as! String);
                    
                    // then we set different 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 are able to lastly return the ViewController to be hooked up to the FlutterPlatformView UIView
                return vc
            }
        case .viewController2:
            if params != nil {
                var vc : UIViewController = UIViewController()
                // first we get the binaryMessenger from params because 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 wants a binaryMessenger
                    // than usually we take from AppDelegate rootViewController, however as it is a Plug-in we haven't any AppDelegate
                    let vcToShow = ViewController2(withParameter: binaryMessenger, methodChannelId: params!["methodChannelId"] as! String);
                    
                    // then we set different 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 are able to lastly return the ViewController to be hooked up to the FlutterPlatformView UIVIew
                return vc
            }

        }
        return nil
    }
}
import Flutter
import UIKit


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

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

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

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

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

            vc = vcToShow
                // _view = vcToShow.view /// breaks contact
            }
        }
        tremendous.init()
        // _view.addSubview(vc.view)
    }

    func view() -> UIView {
        // _view.addSubview(vc.view)
        // return _view
        return vc.view
    }
}

import Flutter
import UIKit

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

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

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

  public func deal with(_ name: FlutterMethodCall, consequence: @escaping FlutterResult) {
    change name.methodology {
    case "getPlatformVersion":
      consequence("iOS " + UIDevice.present.systemVersion)
    default:
      consequence(FlutterMethodNotImplemented)
    }
  }
}

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

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

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

  @override
  Widget construct(BuildContext context) {
    const String viewType="native_screen";
    closing Map creationParams = widget.viewParams;

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

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

  @override
  Widget construct(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: >{
              Manufacturing unit(
                () => EagerGestureRecognizer(),
              ),
            },
          );
  }
}

Each approaches work however I do not appear to have the ability to discover information about greatest practices or unhealthy practices for this case.

My concern is that whereas registering just one FlutterPlatformViewFactory with the plugin would guarantee that there is no such thing as a id downside as a result of it is just one, this might be result in points like reminiscence leaks for example after I use the plugin widget in several Flutter screens so the plugin would register it once more with the identical id.
I do not discover within the docs any reference about its de-registration, so I do not know if it is a secure strategy as maybe the FlutterPlatformViewFactory will get deregistered when closing the Flutter display screen that makes use of the plugin widget releasing up assets taken because it occurs when a brand new FlutterMethodChannelHandler will get registered on the identical channel de-registering any beforehand registered one or it stays registered anyhow.

Are you able to level me to some a part of the docs I missed or to any article or some Flutter plugin that does have a number of native screens for its UI?
As at all times your assist could be very a lot appreciated

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles