1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/CarGuo-GSYFlutterBook

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Flutter-update-1.12.md 20 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 10.03.2025 00:06 5767d61

Flutter Interact не только представляет новые средства разработки, но и включает в себя выпуск стабильной версии 1.12.

В отличие от предыдущих версий, версия 1.12.x внесла значительное количество небинарно-совместимых изменений в Flutter Framework, такие как добавление параметра DecoderCallback в метод load класса ImageProvider на уровне Dart, увеличение минимальной высоты TextField с 40 до 48, переход PageView на использование SliverLayoutBuilder вместо RenderSliverFillViewport и другие изменения обратной совместимости.

Однако указанные проблемы не являются критическими, так как они могут быть решены путём корректировки соответствующего кода на Dart. Однако самое существенное изменение заключается в обновлении API плагинов для Android, которое требует от пользователей выполнить адаптацию кода модулей Android и плагинов проекта Flutter.

1. Android Plugins

1. Введение

С версии Flutter 1.12 команда Flutter начала использовать новую реализацию API плагинов для Android. После версии 1.12 Android начал использовать новый API плагинов, основанный на старом PluginRegistry.Registrar. Этот последний не будет немедленно прекращен, однако рекомендован переход на новый API FlutterPlugin. Кроме того, официальные плагины теперь полностью используют библиотеку AndroidX.По сравнению со старым API, преимущества нового API заключаются в том, что он предоставляет более декомпозированное использование жизненного цикла для зависимостей плагинов. Например, ранее при использовании PluginRegistry.Registrar.activity(), если Flutter ещё не был добавлен в Activity, то вызов мог вернуть null. Также плагины не знали, когда они были загружены и использованы движком. Новый API решил эти проблемы.

2. Обновление

Для использования нового API Android-плагины должны реализовать FlutterPlugin и MethodCallHandler, а также предоставляют ActivityAware для управления жизненным циклом Activity и получения доступа к нему, а также ServiceAware для управления жизненным циклом Service и получения доступа к нему. Конкретные шаги миграции следуют:

  1. Обновите главный класс плагина (*Plugin.java) для реализации FlutterPlugin, то есть обычно Android-плагины должны наследовать FlutterPlugin и MethodCallHandler. Если требуется использование Activity, то следует наследовать также ActivityAware.Перевод выполнен согласно правилам, указанному типу документа (markdown) и целевому языку (русский).

Раньше плагины Flutter были непосредственными наследниками MethodCallHandler, предоставляя метод registerWith; после обновления код выглядит следующим образом. В новой версии также сохранён метод registerWith для обеспечения обратной совместимости с предыдущими версиями. В новом API метод MethodCallHandler инициализируется и создаётся в методе onAttachedToEngine, а освобождается в методе onDetachedFromEngine. Также предоставлены четыре реализованных метода, связанных с жизненным циклом активности.```java public class FlutterPluginTestNewPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware { private static MethodChannel channel;

// Сохранение обратной совместимости со старыми версиями public static void registerWith(Registrar registrar) { Log.e("registerWith", "registerWith"); channel = new MethodChannel(registrar.messenger(), "flutter_plugin_test_new"); channel.setMethodCallHandler(new FlutterPluginTestNewPlugin()); }

@Override public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { if (call.method.equals("getPlatformVersion")) { Log.e("onMethodCall", call.method); result.success("Android " + android.os.Build.VERSION.RELEASE); Map<String, String> map = new HashMap<>(); map.put("message", "сообщение"); channel.invokeMethod("onMessageTest", map); } else { result.notImplemented(); } }

//// Два метода из интерфейса FlutterPlugin @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { Log.e("onAttachedToEngine", "onAttachedToEngine"); channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "flutter_plugin_test_new"); channel.setMethodCallHandler(new FlutterPluginTestNewPlugin()); }

@Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { Log.e("onDetachedFromEngine", "onDetachedFromEngine"); }

/// Методы жизненного цикла активности @Override public void onAttachedToActivity(ActivityPluginBinding activityPluginBinding) { Log.e("onAttachedToActivity", "onAttachedToActivity"); }

@Override public void onDetachedFromActivityForConfigChanges() { Log.e("onDetachedFromActivityForConfigChanges", "onDetachedFromActivityForConfigChanges"); }

@Override public void onReattachedToActivityForConfigChanges(ActivityPluginBinding activityPluginBinding) { Log.e("onReattachedToActivityForConfigChanges", "onReattachedToActivityForConfigChanges"); } }

  @Override
  public void onDetachedFromActivity() {
    Log.e("onDetachedFromActivity", "onDetachedFromActivity");
  }
}
```---

**Кратко говоря, вам нужно реализовать множественное наследование от интерфейса `FlutterPlugin`, а затем в методе `onAttachedToEngine` создать объект `MethodCallHandler` и вызвать `setMethodCallHandler`. После этого аналогичным образом выполните инициализацию в оставшемся методе `registerWith`.**

При нормальной работе плагин будет вызывать следующие входные данные:

```
2019-12-19 18:01:31.481 24809-24809/? E/onAttachedToEngine: onAttachedToEngine
2019-12-19 18:01:31.481 24809-24809/? E/onAttachedToActivity: onAttachedToActivity
2019-12-19 18:01:31.830 24809-24809/? E/onMethodCall: getPlatformVersion
2019-12-19 18:05:48.051 24809-24809/com.shuyu.flutter_plugin_test_new_example E/onDetachedFromActivity: onDetachedFromActivity
2019-12-19 18:05:48.052 24809-24809/com.shuyu.flutter_plugin_test_new_example E/onDetachedFromEngine: onDetachedFromEngine
```

Кроме того, **если ваш плагин предназначен для лучшей совместимости с более старыми версиями Flutter Plugin, то статический метод `registerWith` следует изменить на следующий код:**

```
public static void registerWith(Registrar registrar) {
  channel = new MethodChannel(registrar.messenger(), "flutter_plugin_test_new");
  channel.startListening(registrar.messenger());
}
```

---

Если плагин написан на Kotlin, изменения могут выглядеть следующим образом.

![](http://img.cdn.guoshuyu.cn/20191227_Flutter-update-1.12/image1)2\. Если это возможно, можно изменить объект `MainActivity` основного проекта, **заменив наследование от `FlutterActivity` из пакета `io.flutter.app.FlutterActivity` на `io.flutter.embedding.android.FlutterActivity`. В этом случае плагины будут автоматически регистрироваться; если же это невозможно, придется самостоятельно вызвать метод `GeneratedPluginRegistrant.registerWith()`.** Конечно, при этом может возникнуть предупреждение о неправильном вызове `registerWith()`.```
/// Этот метод требует самостоятельного вызова, если в трех вариантах AndroidManifest.xml не включена конфигурация flutterEmbedding v2
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
    GeneratedPluginRegistrant.registerWith(flutterEngine);
}
```

> Если вы используете три варианта AndroidManifest.xml с включенной конфигурацией flutterEmbedding v2, тогда сгенерированный `GeneratedPluginRegistrant` будет использовать `FlutterEngine`; если же конфигурация v2 не используется, то будет использоваться `PluginRegistry`. После этого потребуется также отредактировать файл `AndroidManifest.xml`, как показано ниже. Необходимо удалить существующий `meta-data` с именем `io.flutter.app.android.SplashScreenUntilFirstFrame`, а затем добавить два новых `meta-data`: `io.flutter.embedding.android.SplashScreenDrawable` и `io.flutter.embedding.android.NormalTheme`. Это используется для установки стилей placeholder при запуске приложения и темы после запуска.

![](http://img.cdn.guoshuyu.cn/20191227_Flutter-update-1.12/image2)

**Здесь следует обратить внимание, что, как показано выше, требуется конфигурация `flutterEmbedding` внутри узла `application`, чтобы включить новую логику загрузки плагинов.**

```xml
<meta-data
    android:name="flutterEmbedding"
    android:value="2" />
```

4. После этого можно выполнить команду `flutter packages get`, чтобы сгенерировать новый файл `GeneratedPluginRegistrant`. Как показано ниже, новые `FlutterPlugin` будут загружаться непосредственно через `flutterEngine.getPlugins().add`, а старые реализации плагинов будут совместимо загружены через `ShimPluginRegistry` в реализацию версии 2.```java
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.view.FlutterView;

public final class GeneratedPluginRegistrant {
  public static void registerWith(PluginRegistry registry) {
    if (registry.hasPlugin("shared_preferences")) {
      new SharedPreferencesPlugin().onRegister(registry.registrarFor("shared_preferences"));
    }
    // Добавление других плагинов аналогично
  }
}
```  private static void addPlugins(FlutterView view, PluginRegistry registry) {
     view.getPlugins().add(new FlutterEnginePlugin());
     // Добавление других плагинов аналогично
   }
 }

@Keep public final class GeneratedPluginRegistrant { public static void registerWith(@NonNull FlutterEngine flutterEngine) { ShimPluginRegistry shimPluginRegistry = new ShimPluginRegistry(flutterEngine); flutterEngine.getPlugins().add(new io.flutter.plugins.androidintent.AndroidIntentPlugin()); flutterEngine.getPlugins().add(new io.flutter.plugins.connectivity.ConnectivityPlugin()); flutterEngine.getPlugins().add(new io.flutter.plugins.deviceinfo.DeviceInfoPlugin()); io.github.ponnamkarnik.toast.fluttertoast.FluttertoastPlugin.registerWith(shimPluginRegistry.registrarFor("io.github.ponnamkarnik.toast.fluttertoast.FluttertoastPlugin")); flutterEngine.getPlugins().add(new io.flutter.plugins.packageinfo.PackageInfoPlugin()); flutterEngine.getPlugins().add(new io.flutter.plugins.pathprovider.PathProviderPlugin()); com.baseflow.permissionhandler.PermissionHandlerPlugin.registerWith(shimPluginRegistry.registrarFor("com.baseflow.permissionhandler.PermissionHandlerPlugin")); flutterEngine.getPlugins().add(new io.flutter.plugins.share.SharePlugin()); flutterEngine.getPlugins().add(new io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin()); com.tekartik.sqflite.SqflitePlugin.registerWith(shimPluginRegistry.registrarFor("com.tekartik.sqflite.SqflitePlugin")); flutterEngine.getPlugins().add(new io.flutter.plugins.urllauncher.UrlLauncherPlugin()); flutterEngine.getPlugins().add(new io.flutter.plugins.webviewflutter.WebViewFlutterPlugin()); } } 5. Последним шагом является необязательное обновление в файле `gradle-wrapper.properties`, который находится в директории `android/gradle/wrapper`. Вы можете изменить значение `distributionUrl` на `https\://services.gradle.org/distributions/gradle-5.6.2-all.zip`. Вместе с этим вам потребуется также обновить версию Gradle в файле build.gradle, расположенном в директории android/ до значения com.android.tools.build:gradle:3.5.0. Также можно обновить версию плагина Kotlin до '1.3.50'.### Другие обновления

  1. Если ваш проект ещё не использует Androidx, вы можете добавить следующий код в файл gradle.properties, расположенный в директории android/, чтобы активировать его:

    android.enableR8=true
    android.useAndroidX=true
    android.enableJetifier=true
  2. Нужно добавить .flutter-plugins-dependencies в список игнорируемых файлов.

  3. После обновления, если у вас возникли вопросы относительно увеличения размера пакета iOS, вы можете обратиться к сообществу GitHub, где подробно объясняется причина этого поведения. Кроме того, если вы столкнулись с проблемой отсутствия логов при работе с реальным устройством iOS 13, рекомендуется просмотреть этот issue.

Изображение

  1. Как показано на следующем рисунке, в процессе обновления до версии 1.12.x был изменён файл Podfile для iOS. При использовании старого файла могут появиться соответствующие предупреждения. Ниже приведены примеры таких конфигураций.

Изображение

# Отмените этот символ, чтобы определить глобальную платформу для вашего проекта
# platform :ios, '9.0'

# Аналитика CocoaPods отправляет сетевые данные синхронно, что может влиять на время сборки Flutter.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
  'Debug' => :debug,
  'Profile' => :release,
  'Release' => :release,
}
``````ruby
def parse_KV_file(file, separator='=')
  file_abs_path = File.expand_path(file)
  if !File.exist?(file_abs_path)
    return []
  end
  generated_key_values = {}
  skip_line_start_symbols = ['#', '/']
  File.foreach(file_abs_path) do |line|
    next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
    plugin = line.split(separator)
    if plugin.length == 2
      podname = plugin[0].strip()
      path = plugin[1].strip()
      podpath = File.expand_path("#{path}", file_abs_path)
      generated_key_values[podname] = podpath
    else
      puts "Неверное определение плагина: #{line}"
    end
  end
  generated_key_values
end
target 'Runner' do
  use_frameworks!
  use_modular_headers!

  # Flutter Pod

  copied_flutter_dir = File.join(__dir__, 'Flutter')
  copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
  copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
  unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
    # Копируем Flutter.framework и Flutter.podspec в Flutter/, чтобы было что связывать, если скрипт бэкэнда Xcode ещё не запущен.
    # Этот скрипт скопирует правильную версию фреймворка для отладки/профиля/релиза в зависимости от текущей выбранной конфигурации Xcode.
    # CocoaPods не будет внедрять фреймворк при установке пакета (до того как любые этапы сборки могут сгенерировать его), если dylib не существует.

    generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
    unless File.exist?(generated_xcode_build_settings_path)
      raise "Файл Generated.xcconfig должен существовать. Если вы запускаете pod install вручную, убедитесь, что flutter pub get выполнено перед этим"
    end
    generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
    cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']
  end
end
``````ruby
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['ENABLE_BITCODE'] = 'NO'
    end
  end
end

Хорошо, пока всё.

Ссылка на статьи по Flutter:

Полный гид по Flutter

Серия статей "Мир Flutter"

Рекомендованные ресурсы


Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/CarGuo-GSYFlutterBook.git
git@api.gitlife.ru:oschina-mirror/CarGuo-GSYFlutterBook.git
oschina-mirror
CarGuo-GSYFlutterBook
CarGuo-GSYFlutterBook
master