Flutter for Android 开发者

聂永怡
2023-12-01

Views

Flutter和Android中的View

在Flutter中,View相当于是Widget。然而,与View相比,Widget有一些不同之处。 首先,Widget仅支持一帧,并且在每一帧上,Flutter的框架都会创建一个Widget实例树(译者语:相当于一次性绘制整个界面)。 相比之下,在Android上View绘制结束后,就不会重绘,直到调用invalidate时才会重绘。

与Android的视图层次系统不同(在framework改变视图),而在Flutter中的widget是不可变的,这允许widget变得超级轻量。

如何更新widget

在Android中,您可以通过直接对view进行改变来更新视图。然而,在Flutter中Widget是不可变的,不会直接更新,而必须使用Widget的状态。State对象,它可以跨帧存储状态数据并恢复它。

如何布局? XML layout 文件跑哪去了?

在Android中,您通过XML编写布局,但在Flutter中,您可以使用widget树来编写布局。

如何在布局中添加或删除组件

在Android中,您可以从父级控件调用addChild或removeChild以动态添加或删除View。 在Flutter中,因为widget是不可变的,所以没有addChild。但是,您可以传入一个函数,该函数返回一个widget给父项,并通过布尔值控制该widget的创建。

在Android中,可以通过View.animate()对视图进行动画处理,那在Flutter中怎样才能对Widget进行处理

在Flutter中,可以通过动画库给widget添加动画。

在Android中,您可以通过XML创建动画或在视图上调用.animate()。在Flutter中,您可以将widget包装到Animation中。

与Android相似,在Flutter中,您有一个AnimationController和一个Interpolator, 它是Animation类的扩展,例如CurvedAnimation。您将控制器和动画传递到AnimationWidget中,并告诉控制器启动动画。

如何使用Canvas draw/paint

在Android中,您可以使用Canvas在屏幕上绘制自定义形状。

Flutter有两个类可以帮助您绘制画布,CustomPaint和CustomPainter,它们实现您的算法以绘制到画布。

如何构建自定义 Widgets

在Android中,您通常会继承View或已经存在的某个控件,然后覆盖其绘制方法来实现自定义View。

在Flutter中,一个自定义widget通常是通过组合其它widget来实现的,而不是继承。

Intents

Intent在Flutter中等价于什么?

在Android中,Intents主要有两种使用场景:在Activity之间切换,以及调用外部组件。 Flutter不具有Intents的概念,但如果需要的话,Flutter可以通过Native整合来触发Intents。

要在Flutter中切换屏幕,您可以访问路由以绘制新的Widget。 管理多个屏幕有两个核心概念和类:Route 和 Navigator。Route是应用程序的“屏幕”或“页面”的抽象(可以认为是Activity), Navigator是管理Route的Widget。Navigator可以通过push和pop route以实现页面切换。

和Android相似,您可以在AndroidManifest.xml中声明您的Activities,在Flutter中,您可以将具有指定Route的Map传递到顶层MaterialApp实例

如何在Flutter中处理来自外部应用程序传入的Intents

Flutter可以通过直接与Android层通信并请求共享的数据来处理来自Android的Intents

在这个例子中,我们注册文本共享intent,所以其他应用程序可以共享文本到我们的Flutter应用程序

这个应用程序的基本流程是我们首先处理Android端的共享文本数据,然后等待Flutter请求数据,然后通过MethodChannel发送。

startActivityForResult 在Flutter中等价于什么

处理Flutter中所有路由的Navigator类可用于从已经push到栈的路由中获取结果。 这可以通过等待push返回的Future来完成。例如,如果您要启动让用户选择其位置的位置的路由,则可以执行以下操作:

Map coordinates = await Navigator.of(context).pushNamed('/location');

然后在你的位置路由中,一旦用户选择了他们的位置,你可以将结果”pop”出栈

Navigator.of(context).pop({"lat":43.821757,"long":-79.226392});

异步UI

runOnUiThread 在Flutter中等价于什么

Dart是单线程执行模型,支持Isolates(在另一个线程上运行Dart代码的方式)、事件循环和异步编程。 除非您启动一个Isolate,否则您的Dart代码将在主UI线程中运行,并由事件循环驱动(译者语:和JavaScript一样)。例如,您可以在UI线程上运行网络请求代码而不会导致UI挂起(译者语:因为网络请求是异步的)。

AsyncTask和IntentService在Flutter中等价于什么

在Android中,当你想访问一个网络资源时,你通常会创建一个AsyncTask,它将在UI线程之外运行代码来防止你的UI被阻塞。 AsyncTask有一个线程池,可以为你管理线程。

由于Flutter是单线程的,运行一个事件循环(如Node.js),所以您不必担心线程管理或者使用AsyncTasks、IntentServices。

要异步运行代码,可以将函数声明为异步函数,并在该函数中等待这个耗时任务。

在Android上,当您继承AsyncTask时,通常会覆盖3个方法,OnPreExecute、doInBackground和onPostExecute。 在Flutter中没有这种模式的等价物,因为您只需等待一个长时间运行的函数,而Dart的事件循环将负责其余的事情。

但是,有时您可能需要处理大量数据,导致UI可能会挂起。

在这种情况下,与AsyncTask一样,在Flutter中,可以利用多个CPU内核来执行耗时或计算密集型任务。这是通过使用Isolates来完成的。

是一个独立的执行线程,它运行时不会与主线程共享任何内存。这意味着你不能从该线程访问变量或通过调用setState来更新你的UI。

项目结构和资源

在哪里存储分辨率相关的图片文件? HDPI/XXHDPI

Flutter遵循像iOS这样简单的3种分辨率格式: 1x, 2x, and 3x.

创建一个名为images的文件夹,并为每个图像文件生成一个@2x和@3x文件,并将它们放置在如下这样的文件夹中

…/my_icon.png

…/2.0x/my_icon.png
…/3.0x/my_icon.png
然后,您需要在pubspec.yaml文件中声明这些图片

assets:
 - images/a_dot_burr.jpeg
 - images/a_dot_ham.jpeg

然后您可以使用AssetImage访问您的图像

return new AssetImage("images/a_dot_burr.jpeg");

在哪里存储字符串? 如何存储不同的语言

目前,最好的做法是创建一个名为Strings的类

class Strings{
  static String welcomeMessage = "Welcome To Flutter";
}

然后在你的代码中,你可以像访问你的字符串一样:

new Text(Strings.welcomeMessage)

Flutter对Android的可访问性提供了基本的支持,虽然这个功能正在进行中。

鼓励Flutter开发者使用intl package 进行国际化和本地化。

如何监听Android Activity生命周期事件

在Android中,您可以覆盖Activity的方法来捕获Activity的生命周期回调。

在Flutter中您可以通过挂接到WidgetsBinding观察并监听didChangeAppLifecycleState更改事件来监听生命周期事件

您可以监听到的生命周期事件是

  • resumed - 应用程序可见并响应用户输入。这是来自Android的onResume
  • inactive -应用程序处于非活动状态,并且未接收用户输入。此事件在Android上未使用,仅适用于iOS
  • paused -应用程序当前对用户不可见,不响应用户输入,并在后台运行。这是来自Android的暂停
  • suspending -该应用程序将暂时中止。这在iOS上未使用
 类似资料: