Android 开发者的 Flutter 指南 — Intent
2019-02-25 本文已影响15人
敲代码的本愿
Intent 在 Flutter 中对应什么?
Flutter 没有 Intent 的概念,但仍可通过插件间接使用。
通过 Navigator 和 Route 跳转页面,且都在同一 Activity 。
Route: 理解为页面。类似于 Activity ,但含义不同。
Navigator: 用来管理 Route 的 Widget ,通过 push() 跳转或 pop() 回退。
页面跳转的方式:
- MaterialApp:指定 route 名称的 Map。
void main() {
runApp(MaterialApp(
home: MyAppHome(), // becomes the route named '/'
routes: <String, WidgetBuilder> {
'/a': (BuildContext context) => MyPage(title: 'page A'),
'/b': (BuildContext context) => MyPage(title: 'page B'),
'/c': (BuildContext context) => MyPage(title: 'page C'),
},
));
}
//跳转
Navigator.of(context).pushNamed('/b');
- WidgetApp:直接导航到一个 route。
要在 Flutter 中使用类似 Intent 调用外部组件,如相机、相册的功能,则需要在本地平台中集成,或使用现有插件。
关于创建本地集成平台,参阅 Developing Packages and Plugins 。
如何处理来自外部程序的 Intent ?
Flutter 可以直接通过来自 Android 的 Intent 与 Android 层进行交互并请求共享数据。
下面示例,在一个运行 Flutter 代码的本地 activity 中注册一个分享文本的 Intent 过滤器,然后其他应用可以与 Flutter 应用分享文本。
基本流程,首先在 Android 本地(Activiy)处理分享的文本数据,然后等待 Flutter 请求数据,并使用 MethodChannel 返回给 Flutter。
- 在 AndroidManifest.xml 中为所有 Intent 注册过滤器:
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- ... -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
- 在 MainActivity 中处理 Intent,获取共享文本数据,并持有它。当 Flutter 请求数据时,从本地端发送过去:
package com.example.shared;
import android.content.Intent;
import android.os.Bundle;
import java.nio.ByteBuffer;
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.ActivityLifecycleListener;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
private String sharedText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("text/plain".equals(type)) {
handleSendText(intent); // Handle text being sent
}
}
new MethodChannel(getFlutterView(), "app.channel.shared.data").setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
if (call.method.contentEquals("getSharedText")) {
result.success(sharedText);
sharedText = null;
}
}
});
}
void handleSendText(Intent intent) {
sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
}
}
- 当 Flutter 层展示 Widget 时请求数据:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(SampleApp());
}
class SampleApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample Shared App Handler',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
static const platform = const MethodChannel('app.channel.shared.data');
String dataShared = "No data";
@override
void initState() {
super.initState();
getSharedText();
}
@override
Widget build(BuildContext context) {
return Scaffold(body: Center(child: Text(dataShared)));
}
getSharedText() async {
var sharedData = await platform.invokeMethod("getSharedText");
if (sharedData != null) {
setState(() {
dataShared = sharedData;
});
}
}
}
startActivityForResult() 对应什么 ?
通过等待(await) Navigator 的 push() 方法获取返回结果。
示例:
//跳转 location 页面
Map coordinates = await Navigator.of(context).pushNamed('/location');
//在 location 页面,通过 pop方法返回结果
Navigator.of(context).pop({"lat":43.821757,"long":-79.226392});
原文给 Android 开发者的 Flutter 指南,参考 Android 开发者参考。
此文目的:仅与 Android 对比,尽可能言简意骇的翻译,且不遗漏、不曲解词义。